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

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

概要

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

このような問題の発生を抑えるために、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() が導入されています。システムがサービスを作成した後、アプリは 5 秒以内にサービスの [startForeground()](/reference/android/app/Service#startForeground(int, android.app.Notification) メソッドを呼び出して、新しいサービスのユーザー表示通知を表示する必要があります。アプリが制限時間内に 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)以降をターゲットとするアプリにのみ影響します。ただし、アプリが 26 より低い API レベルをターゲットとしている場合でも、ユーザーは [設定] 画面から任意のアプリに対してこれらの制限を有効にできます。新しい制限に準拠するようアプリを更新しなければならない場合があります。

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

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

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

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