この記事は Androidスマホ用のアプリ開発の中で、
今後の開発で再使用性が高いと思われるコーディングをまとめたものです。
Java での開発経験、XML構文規則、Android のアプリ開発経験がある方を対象としています。
Android のアプリ開発でお役にたててれば、嬉しいです。
(これから Android のアプリ開発や Java での開発を始めたい方への案内は、記事の最後で紹介します)
マニフェストファイルにフォアグラウンドサービスタイプの宣言を追加する場合、
Google Play Consoleからフォアグラウンドサービスタイプの申告が必要になりました。
権限の使用を申告していない、間違って申告している場合、ポリシー違反でリリースが否認されます。
ポイント
Android14でコア機能にいくつか変更がありました。
そのひとつが「フォアグラウンドサービスタイプは必須」です。
対応していないアプリは、フォアグラウンドサービスを起動したときにアプリが落ちます。
今回は、「フォアグラウンドサービスタイプは必須」の対応方法について、紹介します。
フォアグラウンドサービスの起動
フォアグラウンドサービスは通知を表示することで、ユーザが起動していることを認識できるサービスです。
フォアグラウンドサービスタイプの宣言
マニフェストファイル(AndroidManifest.xml)にアプリから起動するフォアグラウンドサービスの使用をリクエストする権限を宣言します。
また、起動するフォアグラウンドサービスのタイプを要素内に新しく追加されたforegroundServiceTypeに定義します。
サンプルでは、タイプとして位置情報の権限をリクエスト、foregroundServiceTypeを定義しています。
…
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
…
<service android:name=".TodoService"
android:foregroundServiceType="location"/>
…
選択可能なフォアグラウンドサービスタイプ、マニフェスト ファイルで宣言する必要がある権限は、公式サイトのフォアグラウンドサービスタイプは必須で確認できます。
Google Play Consoleのアプリのコンテンツで、使用するフォアグラウンドサービスタイプを申告します。
実行時にフォアグラウンドサービスタイプを含める
Android14から、指定が必要なフォアグラウンドサービスは開始時にフォアグランドサービスタイプの指定が必須になりました。
Android10から、フォアグラウンドサービスタイプが指定できるようになりましたので、startForegroundの実行は OSバージョンの判断が必要です。
サンプルは音楽を再生するサービスのため、ExoPlayerを使用しています。
また、位置情報を使用するサービスでもあるため、サービス開始時にフォアグランドサービスタイプとして、FOREGROUND_SERVICE_TYPE_LOCATIONを指定しています。
public class TodoService extends Service
implements FusedLocationManager.OnLocationResultListener {
private static final String TAG = TodoService.class.getSimpleName();
private static final int REQUEST_CODE = 2023;
private ExoPlayer exoPlayer;
private NotificationManager notificationManager;
private MediaSession mediaSession;
private androidx.media3.session.MediaStyleNotificationHelper.MediaStyle
mediaStyle;
private PendingIntent pendingIntentList;
…
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
…
exoPlayer = new ExoPlayer.Builder(context)
.setHandleAudioBecomingNoisy(true)
.build();
…
mediaSession = new MediaSession.Builder(context, exoPlayer).build();
…
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
…
// mediaStyle
mediaStyle = new MediaStyleNotificationHelper.MediaStyle(mediaSession);
mediaStyle.setShowActionsInCompactView(0,1,2);
// PendingIntentList
pendingIntentList = PendingIntent.getActivity(context, REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE);
// Notification
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(TAG, TAG, NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("Silent Notification");
channel.setSound(null, null);
channel.enableLights(false);
channel.setLightColor(R.color.blue);
channel.enableVibration(false);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
Notification notification;
if (intent.getIntExtra("MUSIC", 0) > 0)
notification = new NotificationCompat.Builder(context, TAG)
.setContentTitle(context.getString(R.string.app_name))
.setContentText(TAG)
.setContentIntent(pendingIntentList)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_timer)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.logo))
.setStyle(mediaStyle)
.addAction(new NotificationCompat.Action(R.drawable.ic_round_rwd, RWD, CustomMediaButtonReceiver.buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)))
.addAction(pause ? new NotificationCompat.Action(R.drawable.ic_round_play, PLAY, CustomMediaButtonReceiver.buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_PLAY)) :
new NotificationCompat.Action(R.drawable.ic_round_pause, PAUSE, CustomMediaButtonReceiver.buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_PAUSE)))
.addAction(new NotificationCompat.Action(R.drawable.ic_round_fwd, FWD, CustomMediaButtonReceiver.buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_SKIP_TO_NEXT)))
.build();
else
notification = new NotificationCompat.Builder(context, TAG)
.setContentTitle(context.getString(R.string.app_name))
.setContentText(TAG)
.setContentIntent(pendingIntentList)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_timer)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.logo))
.setStyle(new androidx.media.app.NotificationCompat.MediaStyle())
.build();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(ID, notification, FOREGROUND_SERVICE_TYPE_LOCATION);
} else {
startForeground(ID, notification);
}
}
…
指定が必要なフォアグランドサービス
FOREGROUND_SERVICE_TYPE_CAMERA
FOREGROUND_SERVICE_TYPE_LOCATION
FOREGROUND_SERVICE_TYPE_MICROPHONE
ExoPlayerについては、ExoPlayerで動画や音楽を再生するで紹介しています。
通知については、Android13対応(実行時の通知権限)で紹介しています。
USDケーブルは規格によって、性能が全く違います。
急速充電・高速データ転送で選ぶならコレです♪
今回は、ここまでです。
フォアグラウンドサービスタイプは必須に対応している Androidアプリです。
アプリの中でフォアグラウンドサービスを起動しています。
誤字脱字、意味不明でわかりづらい、
もっと詳しく知りたいなどのご意見は、
このページの最後にあるコメントか、
こちらから、お願いいたします♪
ポチッとして頂けると、
次のコンテンツを作成する励みになります♪
これからAndroidのアプリ開発やJavaでの開発を始めたい方へ
アプリケーション開発経験がない方や、アプリケーション開発経験がある方でも、Java や C# などのオブジェクト指向言語が初めての方は、Android のアプリ開発ができるようになるには、かなりの時間がかかります。オンラインスクールでの習得を、強くおススメします。
未経験者からシステムエンジニアを目指すのに最適かと、まずは無料相談から♪
未経験者からプログラマーを目指すのに最適かと、まずは無料カウンセリングから♪
カリキュラムとサポートがしっかりしています、お得なキャンペーンとかいろいろやっています♪
ゲーム系に強いスクール、UnityやUnrealEngineを習得するのに最適かと、まずは無料オンライン相談から♪
参考になったら、💛をポッチとしてね♪
コメント欄