Save the date! Android Dev Summit is coming to Mountain View, CA on November 7-8, 2018.

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

アプリがバックグラウンドで実行されているときは必ず端末のリソースの一部(RAM など)を消費します。 これにより、ユーザー エクスペリエンスが悪化する場合があります。特にゲームをプレイしたり動画を視聴したりするなど、多くのリソースを消費するアプリを使用している場合、この傾向が強くなります。

Android 8.0 では、ユーザー エクスペリエンスを向上させるために、アプリがバックグラウンドで実行されているときの動作を制限しています。 このドキュメントでは、オペレーティング システムへの変更点を説明し、新しい制限下でアプリを良好に動作させるためのアップデート方法を説明します。

概要

多くの Android アプリやサービスは同時に実行することができます。 たとえば、あるウィンドウでゲームをプレイしながら別のウィンドウでウェブをブラウジングしているときに、別のアプリで音楽を再生できます。

同時に実行するアプリが多いほど、システムに大きな負荷がかかります。 さらに多くのアプリやサービスがバックグラウンドで実行されると、システムにかかる負荷が増えて、音楽アプリが突然シャットダウンするなど、ユーザー エクスペリエンスが低下します。

Android 8.0 では、このような問題の発生頻度を抑えるため、ユーザーがアプリを直接操作していないときにアプリで実行できる動作を制限しています。

アプリの動作は次の 2 つの方法で制限されます。

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

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

注: デフォルトでは、これらの制限は O を対象とするアプリのみに適用されますが、 アプリが O を対象としていない場合でも、ユーザーは [Settings] 画面でアプリに対してこれらの制限を有効にすることができます。

ほとんどの場合、アプリは JobScheduler ジョブを使用してこれらの制限を回避できます。 このアプローチでは、アプリがアクティブに実行されていないときに動作を実行するように調整できますが、アプリがユーザー エクスペリエンスに影響しないようにこれらのジョブをスケジュールすることも可能です。

Android 8.0 では、JobScheduler にいくつかの改善が追加されており、サービスとブロードキャスト レシーバーをスケジュールされたジョブに簡単に置き替えることができます。詳細については、JobScheduler の改善をご覧ください。

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

バックグラウンドで実行されているサービスが端末のリソースを消費して、ユーザー エクスペリエンスに悪影響を及ぼす可能性があります。 システムでは、この問題を軽減するために、サービスに対して多くの制限を適用しています。

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

  • 可視アクティビティがある(アクティビティが開始されているか一時停止されているかに関係なく)。
  • フォアグラウンド サービスを使用している。
  • 別のフォアグラウンド アプリが該当アプリのいずれかのサービスにバインドされるか、該当アプリのいずれかのコンテンツ プロバイダを使用することで、フォアグラウンド アプリが該当アプリに接続している。 たとえば、別のアプリが次のいずれかのサービスにバインドされると、アプリがフォアグラウンドになります。

    • IME
    • 壁紙サービス
    • 通知リスナー
    • 音声またはテキスト サービス

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

アプリがフォアグラウンドにある場合、そのアプリはフォアグラウンド サービスとバックグラウンド サービスの両方を制限なく作成して実行できます。 アプリがバックグラウンドに移行すると数分間のウィンドウが提供され、アプリはそのウィンドウ内でサービスを作成して使用できます。

そのウィンドウの終了時に、アプリは アイドル状態 であると見なされます。 システムはこの時点で、アプリがサービスの Service.stopSelf() メソッドを呼び出したかのように、アプリのバックグラウンド サービスを停止します。

特定の状況下では、バックグラウンド アプリは一時的なホワイトリストに数分間入れられます。 アプリがこのホワイトリストに存在する間は、アプリは制限なくサービスを起動でき、アプリのバックグラウンド サービスは実行が許可されます。

アプリは、ユーザーに表示される次のようなタスクを処理しているときにホワイトリストに入れられます。

多くの場合、アプリではバックグラウンド サービスを JobScheduler ジョブに置き換えることができます。 たとえば、CoolPhotoApp はこのアプリがフォアグラウンドで実行されていない場合でも、ユーザーが友人から共有写真を受信したかどうかを確認する必要があります。

このアプリでは以前、アプリのクラウド ストレージをチェックするバックグラウンド サービスを使っていました。 Android 8.0 に移行するには、バックグラウンド サービスをスケジュールされたジョブに置き換えます。スケジュールされたジョブは、定期的に起動され、サーバーに対してクエリを実行してから終了します。

Android 8.0 よりも前のバージョンでは、フォアグラウンド サービスを作成する通常の方法として、バックグラウンド サービスを作成してから、そのサービスをフォアグラウンドにプロモートしていました。

Android 8.0 では、追加機能があります。システムは、バックグラウンド アプリによるバッグラウンド サービスの作成を許可しません。 そのため、Android 8.0 では、フォアグラウンドで新しいサービスを作成する Context.startForegroundService() メソッドが新たに導入されています。

システムによってサービスが作成されると、アプリは、サービスの startForeground() メソッドを 5 秒以内に呼び出して、その新しいサービスの通知をユーザーに表示します。

アプリが startForeground() を制限時間内に呼び出さない場合、サービスが停止し、アプリが ANR になります。

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

アプリがブロードキャストを受信するように登録されている場合、ブロードキャストが送信されるたびにアプリのレシーバーがリソースを消費します。 そのため、非常に多くのアプリがシステム イベントに基づくブロードキャストの受信を登録している場合、問題が発生する可能性があります。ブロードキャストをトリガーするシステム イベントより、これらのすべてのアプリが続けざまにリソースを消費して、ユーザー エクスペリエンスに悪影響を与える可能性があります。

Android 7.0(API レベル 25)では、この問題を軽減するために、バックグラウンド処理の最適化で説明しているように、ブロードキャストに制限を課しています。

Android 8.0 では、これらの制限を強化しています。

  • Android 8.0 を対象にしているアプリは、暗黙的なブロードキャストに対するブロードキャスト レシーバーをマニフェストで登録できなくなりました。 暗黙的なブロードキャストとは、ターゲットにするアプリを明確に指定しないブロードキャストです。 たとえば、ACTION_PACKAGE_REPLACED は暗黙的なブロードキャストです。これは登録されたすべてのリスナーに送信され、これらのリスナーに端末上のパッケージが置き換えられたことを通知します。

    一方、ACTION_MY_PACKAGE_REPLACED は暗黙的なブロードキャストではありません。これはパッケージが置き換えられたアプリのみに送信されます。その他のアプリがそのブロードキャストに対してリスナーを登録していても、受信するアプリは 1 つのみです。

  • アプリは引き続き明示的なブロードキャストをマニフェスト内で登録できます。

  • アプリは実行時に Context.registerReceiver() を使って、暗黙的、明示的を問わず任意のブロードキャストに対するレシーバーを登録できます。

  • 署名パーミッションが必要なブロードキャストは、端末上のすべてのアプリではなく、同じ証明書で署名されたアプリのみに送信されるため、これらのブロードキャストにはこの制限は適用されません。

多くの場合、以前に暗黙的なブロードキャストに対して登録していたアプリは、JobScheduler ジョブを使用して同様の機能を得ることができます。

たとえば、ソーシャル フォト アプリでは、そのデータを適宜クリーンアップする必要があり、多くの場合、端末の充電中にこの操作が行われます。

以前は、アプリは ACTION_POWER_CONNECTED に対するレシーバーをマニフェスト内で登録しており、ブロードキャストを受信すると、クリーンアップが必要かどうかをチェックしていました。 Android 8.0 に移行するために、アプリではマニフェストからこのレシーバーが削除されました。

その代わり、アプリでは端末がアイドル状態かつ充電中である場合に実行するクリーンアップ ジョブがスケジュールされます。

注: 現在、多くの暗黙的なブロードキャストがこの制限の適用外となっています。 アプリでは、対象とする API レベルとは関係なく、引き続きこれらのブロードキャストに対するレシーバーをマニフェスト内に登録できます。 制限対象外のブロードキャストのリストについては、暗黙的なブロードキャストの例外をご覧ください。

移行ガイド

デフォルトでは、これらの変更は O を対象とするアプリのみ影響を及ぼしますが、 アプリが O を対象としていない場合でも、ユーザーは [Settings] 画面でアプリに対してこれらの制限を有効にすることができます。

新しい制限に準拠するために、アプリをアップデートする必要がある場合があります。

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

考えられる解決策は次のとおりです。

  • アプリがバックグラウンドにあるときに、アプリでフォアグランド サービスを作成する必要がある場合は、バックグラウンド サービスを作成してそれをフォアグランドにプロモートするのではなく、新しい NotificationManager.startServiceInForeground()

    メソッドを使用します。

  • サービスがユーザーに表示される場合、これをフォアグランド サービスにします。 たとえば、音声を再生するサービスは常にフォアグラウンド サービスである必要があります。

    startService() ではなく、NotificationManager.startServiceInForeground() を使ってサービスを作成します。

  • スケジュールされたジョブを使ってサービスの機能を複製する方法を探ります。 ユーザーが認識できる動作がサービスによって直ちに実行されない場合、一般的には、代わりにスケジュールされたジョブを使うことができます。

  • バックグラウンドでポーリングを行うのではなく、FCM を使って、ネットワーク イベントが発生したときにアプリを選択的に起動します。

  • アプリが自然にフォアグランドになるまでバックグラウンドの動作を保留します。

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

  • マニフェストでレシーバーを宣言するのではなく、Context.registerReceiver() を呼び出して実行時にレシーバーを作成します。

  • スケジュールされたジョブを使って、暗黙的なブロードキャストがトリガーされた状況があったかどうかを確認します。