バックグラウンドでの実行の制限

アプリがバックグラウンドで実行されると、デバイスの限られたリソース(RAM など)を消費します。特に、ゲームをプレイしたり動画を視聴したりするなど、リソースを大量に消費するアプリを使用している場合、ユーザー エクスペリエンスが低下する可能性があります。Android 8.0(API レベル 26)では、ユーザー エクスペリエンスを改善するため、バックグラウンドで実行中のアプリの動作に制限を設けています。このドキュメントでは、オペレーティング システムの変更点と、新しい制限の下で適切に動作するようにアプリを更新する方法について説明します。

概要

多くの Android アプリとサービスは同時に実行できます。たとえば、あるウィンドウでゲームをプレイしながら、別のウィンドウでウェブをブラウジングし、3 つ目のアプリを使用して音楽を再生している場合があります。同時に実行するアプリが多いほど、システムにかかる負荷が大きくなります。追加のアプリやサービスがバックグラウンドで実行されている場合、システムに余分な負荷がかかり、ユーザー エクスペリエンスが低下する可能性があります。たとえば、音楽アプリが突然シャットダウンする可能性があります。

このような問題が発生する可能性を下げるため、Android 8.0 では、ユーザーが直接アプリを操作していないときにアプリが実行できる操作を制限します。アプリは次の 2 つの方法で制限されます。

  • バックグラウンド サービスの制限事項: アプリがアイドル状態の間、バックグラウンド サービスの使用には制限があります。これは、ユーザーがより認識しやすいフォアグラウンド サービスには適用されません。

  • ブロードキャストの制限事項: 限定された例外を除き、アプリはマニフェストを使用して暗黙的なブロードキャストを登録できません。それらのブロードキャストは実行時にも登録でき、マニフェストを使用して、アプリに特化した明示的なブロードキャストとブロードキャストを登録できます。

ほとんどの場合、アプリは JobScheduler ジョブを使用することでこれらの制限を回避できます。このアプローチでは、アプリがアクティブに実行されていないときに処理を実行するように調整しつつ、ユーザー エクスペリエンスに影響を与えない方法でこれらのジョブをスケジュールする余地がシステムに与えられます。Android 8.0 では、サービスとブロードキャスト レシーバをスケジュールされたジョブに簡単に置き換えられるように、JobScheduler に複数の改善が行われています。詳細については、JobScheduler の改善をご覧ください。

バックグラウンド サービスの制限事項

バックグラウンドで実行されているサービスがデバイス リソースを消費し、ユーザー エクスペリエンスが低下する可能性があります。この問題を軽減するために、システムではサービスにいくつかの制限を適用しています。

システムは、フォアグラウンド アプリとバックグラウンド アプリが区別されます。(サービス制限を目的としたバックグラウンドの定義は、メモリ管理で使用される定義とは異なります。メモリ管理の場合、アプリはバックグラウンドにあり、サービスの起動機能に関連してはフォアグラウンドにある場合があります)。以下のいずれかに該当する場合、アプリはフォアグラウンドにあるとみなされます。

  • 可視アクティビティがある(アクティビティの開始か一時停止かは問わない)。
  • フォアグラウンド サービスを使用している。
  • 別のフォアグラウンド アプリが、いずれかのサービスにバインドするか、いずれかのコンテンツ プロバイダを使用することで、アプリに接続している。たとえば、別のアプリが以下にバインドされている場合、そのアプリはフォアグラウンドにあります。
    • IME
    • 壁紙サービス
    • 通知リスナー
    • 音声またはテキスト サービス

いずれの条件にも該当しない場合、アプリはバックグラウンドにあるとみなされます。

アプリがフォアグラウンドにある場合、フォアグラウンド サービスとバックグラウンド サービスの両方を自由に作成して実行できます。アプリがバックグラウンドに移行すると、数分間はサービスの作成と使用が許可されます。その期間の終了時に、アプリはアイドル状態とみなされます。この時点では、アプリがサービスの Service.stopSelf() メソッドを呼び出した場合と同様に、システムはアプリのバックグラウンド サービスを停止します。

特定の状況下では、バックグラウンド アプリが一時的な許可リストに数分間追加されます。アプリが許可リストに登録されている間は、サービスを無制限に起動でき、アプリのバックグラウンド サービスの実行が許可されます。アプリは、ユーザーに表示される次のようなタスクを処理すると、許可リストに登録されます。

  • 優先度の高い Firebase Cloud Messaging(FCM)メッセージの処理。
  • SMS/MMS メッセージなどのブロードキャストの受信。
  • 通知からの PendingIntent の実行。
  • VPN アプリがフォアグラウンドに昇格する前に VpnService を開始する。

多くの場合、アプリはバックグラウンド サービスを JobScheduler ジョブに置き換えることができます。たとえば、CoolPhotoApp は、アプリがフォアグラウンドで実行されていなくても、ユーザーが友だちから共有された写真を受け取ったかどうかを確認する必要があります。以前は、アプリは、アプリのクラウド ストレージをチェックするバックグラウンド サービスを使用していました。Android 8.0(API レベル 26)に移行する場合、デベロッパーはバックグラウンド サービスをスケジュールされたジョブに置き換えます。スケジュールされたジョブは定期的に起動され、サーバーにクエリを実行して終了します。

Android 8.0 より前では、フォアグラウンド サービスを作成する通常の方法は、バックグラウンド サービスを作成してから、そのサービスをフォアグラウンドにプロモートすることでした。Android 8.0 には追加機能があり、バックグラウンド アプリによるバックグラウンド サービスの作成は許可されていません。このため、Android 8.0 では、フォアグラウンドで新しいサービスを開始する新しいメソッド startForegroundService() が導入されています。システムがサービスを作成した後、アプリはサービスの [startForeground()](/reference/android/app/Service#startForeground(int, android.app.Notification)) メソッドを呼び出して、新しいサービスの通知を 5 秒以内に表示します。アプリが制限時間内に startForeground() を呼び出さない場合、システムはサービスを停止し、アプリが ANR であると宣言します。

ブロードキャストの制限事項

アプリがブロードキャストを受信するように登録されている場合、ブロードキャストが送信されるたびにアプリのレシーバがリソースを消費します。これにより、システム イベントに基づいてブロードキャストを受信するために登録するアプリが多すぎると、問題が発生する可能性があります。ブロードキャストをトリガーするシステム イベントが発生すると、それらのアプリが連続してリソースを消費し、ユーザー エクスペリエンスを損なう可能性があります。この問題を軽減するために、Android 7.0(API レベル 24)では、バックグラウンド処理の最適化で説明されているように、ブロードキャストに制限を設けました。Android 8.0(API レベル 26)では、これらの制限がより厳格になっています。

  • Android 8.0 以降をターゲットとするアプリでは、ブロードキャストが特定のアプリに限定されていない限り、非明示的ブロードキャストのブロードキャスト レシーバをマニフェストに登録できなくなりました。暗黙的ブロードキャストは、アプリ内の特定のコンポーネントをターゲットとしていないブロードキャストです。たとえば、ACTION_PACKAGE_REPLACED は、すべてのアプリに登録されているすべてのリスナーに送信され、デバイス上のパッケージが置き換えられたことを通知します。ブロードキャストは暗黙的であるため、Android 8.0 以降をターゲットとするアプリでは、マニフェスト登録済みのレシーバには配信されません。ACTION_MY_PACKAGE_REPLACED も暗黙的なブロードキャストですが、パッケージが置き換えられたアプリにのみ送信されるため、マニフェスト登録済みのレシーバに配信されます。
  • アプリは引き続き、明示的ブロードキャストをマニフェストで登録できます。
  • アプリは実行時に Context.registerReceiver() を使用して、明示的か暗黙的かにかかわらず、あらゆるブロードキャストのレシーバを登録できます。
  • 署名権限を必要とするブロードキャストは、この制限から除外されます。これらのブロードキャストは、デバイス上のすべてのアプリではなく、同じ証明書で署名されたアプリにのみ送信されるためです。

多くの場合、以前に非明示的ブロードキャストに登録していたアプリは、JobScheduler ジョブを使用することで同様の機能を取得できます。たとえば、ソーシャル写真アプリでは、データをときどきクリーンアップする必要があり、デバイスが充電器に接続されているときにこの処理を行いたい場合があります。以前は、アプリはマニフェストに ACTION_POWER_CONNECTED のレシーバを登録しており、そのブロードキャストを受信すると、クリーンアップが必要かどうかを確認します。Android 8.0 以降に移行するために、アプリはマニフェストからそのレシーバを削除します。代わりにアプリは、デバイスがアイドル状態で充電中のときに実行されるクリーンアップ ジョブをスケジュールします。

移行ガイド

デフォルトでは、これらの変更は Android 8.0(API レベル 26)以降をターゲットとするアプリにのみ影響します。ただし、アプリの API レベルが 26 未満であっても、ユーザーは [設定] 画面でアプリに対してこれらの制限を有効にできます。新しい制限に準拠するために、アプリの更新が必要になる場合があります。

アプリがサービスをどのように使用しているかを確認します。アプリがアイドル状態のときにバックグラウンドで実行されるサービスにアプリが依存している場合は、置き換える必要があります。考えられる解決策は次のとおりです。

  • アプリがバックグラウンドで実行されているときにフォアグラウンド サービスを作成する必要がある場合は、startService() ではなく startForegroundService() メソッドを使用します。
  • サービスがユーザーが認識できる場合は、フォアグラウンド サービスにします。たとえば、音声を再生するサービスは常にフォアグラウンド サービスでなければなりません。startService() の代わりに startForegroundService() メソッドを使用してサービスを作成します。
  • サービスの機能をスケジュールされたジョブと複製する方法を見つける。ユーザーがすぐに認識できる処理をサービスが行っていない場合、通常は代わりにスケジュールされたジョブを使用できます。
  • バックグラウンドでポーリングするのではなく、FCM を使用して、ネットワーク イベントが発生したときにアプリを選択的に復帰させます。
  • アプリが自然にフォアグラウンドになるまで、バックグラウンド処理を延期する。

アプリのマニフェストで定義されているブロードキャスト レシーバを確認します。影響を受ける暗黙的なブロードキャストのレシーバがマニフェストで宣言されている場合は、レシーバを置き換える必要があります。考えられる解決策は次のとおりです。

  • マニフェストでレシーバを宣言するのではなく、Context.registerReceiver() を呼び出して実行時にレシーバを作成します。
  • スケジュールされたジョブを使用して、非明示的ブロードキャストをトリガーする条件を確認します。