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

アプリがバックグラウンドで実行されるたびに、デバイスの限られたリソース(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() が導入されています。システムがサービスを作成した後、アプリは 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)以降をターゲットとするアプリにのみ影響します。ただし、アプリが API レベル 26 未満をターゲットとしている場合、ユーザーは [設定] 画面からすべてのアプリに対してこれらの制限を有効にできます。新しい制限に準拠するために、アプリの更新が必要になる場合があります。

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

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

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

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