バックグラウンド処理に関するシステム制限

バックグラウンド プロセスは、メモリと電池を大量に消費することがあります。たとえば、非明示的ブロードキャストにより、それをリッスンするように登録されているバックグラウンド プロセスが、作業量が少ないにもかかわらず多数開始される可能性があります。これは、デバイスのパフォーマンスとユーザー エクスペリエンスの両方に大きな影響を与える可能性があります。

システムの制限を回避するには、バックグラウンド タスクに適した API を使用してください。ニーズに合った API を選択するには、バックグラウンド タスクの概要のドキュメントをご覧ください。

ユーザーが開始する制限

アプリが Android Vitals に記述されている好ましくない動作を行った場合、そのアプリのシステム リソースへのアクセスを制限するように、システムがユーザーに求めます。

システムは、アプリが過剰なリソースを消費していることを検出すると、ユーザーに通知し、アプリのアクションを制限するオプションをユーザーに提供します。この通知のきっかけとなる動作には、次のようなものがあります。

  1. 過度の wake lock: 画面がオフのときに、1 つの部分的な wake lock が 1 時間保持されている
  2. 過剰なバックグラウンド サービス: API レベルが 26 未満で、バックグラウンド サービスが過剰である場合

詳細な制限はデバイス メーカーが決定します。たとえば、AOSP ビルドでは、制限付きアプリは、アプリがフォアグラウンドにある場合を除き、ジョブの実行、アラームのトリガー、ネットワークの使用ができません。

ネットワーク アクティビティのブロードキャストの受信に関する制限

アプリは、CONNECTIVITY_ACTION ブロードキャストを受信するようにマニフェストに登録しても受信せず、このブロードキャストに依存するプロセスは開始されません。これは、ネットワークの変更をリッスンする、またはデバイスが定額制のネットワークに接続したときに、一括ネットワーク アクティビティを実行するアプリで問題を引き起こす可能性があります。この制限を回避する方法は、すでに Android フレームワークにいくつか存在しますが、どれを選択すべきかはアプリの目的によって異なります。

定額制の接続での作業のスケジュール設定

WorkRequest を作成する場合は、NetworkType.UNMETERED Constraint を追加します。

fun scheduleWork(context: Context) {
    val workManager = WorkManager.getInstance(context)
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
       .setConstraints(
           Constraints.Builder()
               .setRequiredNetworkType(NetworkType.UNMETERED)
               .build()
           )
       .build()

    workManager.enqueue(workRequest)
}

処理の条件が満たされると、アプリはコールバックを受信して、指定された Worker クラスの doWork() メソッドを実行します。

アプリの実行中にネットワーク接続を監視する

実行中のアプリは、登録済みの BroadcastReceiverCONNECTIVITY_CHANGE を引き続きリッスンできます。ただし、ConnectivityManager API は、指定されたネットワーク条件が満たされた場合にのみコールバックをリクエストする、より堅牢な方法を提供します。

NetworkRequest オブジェクトは、NetworkCapabilities の観点からネットワーク コールバックのパラメータを定義します。NetworkRequest.Builder クラスを使用して NetworkRequest オブジェクトを作成します。その後、registerNetworkCallbackNetworkRequest オブジェクトをシステムに渡します。ネットワーク条件が満たされると、アプリはコールバックを受信し、ConnectivityManager.NetworkCallback クラスで定義された onAvailable() メソッドを実行します。

アプリは、終了するか unregisterNetworkCallback() を呼び出すまで、コールバックを受信し続けます。

画像や動画のブロードキャストの受信に関する制限

アプリは ACTION_NEW_PICTURE ブロードキャストと ACTION_NEW_VIDEO ブロードキャストを送受信できません。この制限により、新しい画像や動画を処理するために複数のアプリを復帰させる必要がある場合に、パフォーマンスとユーザー エクスペリエンスへの影響を軽減できます。

処理をトリガーしたコンテンツ認証局を特定する

WorkerParameters を使用すると、処理をトリガーしたコンテンツ認証局と URI に関する有用な情報を、アプリで受け取ることができます。

List<Uri> getTriggeredContentUris()

処理をトリガーした URI のリストを返します。処理をトリガーした URI がない場合(たとえば、デッドラインなどの理由で処理がトリガーされた場合)、または変更された URI の数が 50 を超える場合は、空になります。

List<String> getTriggeredContentAuthorities()

処理をトリガーしたコンテンツ認証局の文字列リストを返します。返されたリストが空でない場合は、getTriggeredContentUris() を使用して変更された URI の詳細を取得します。

次のサンプルコードは、CoroutineWorker.doWork() メソッドをオーバーライドし、ジョブをトリガーしたコンテンツ認証局と URI を記録します。

class MyWorker(
    appContext: Context,
    params: WorkerParameters
): CoroutineWorker(appContext, params)
    override suspend fun doWork(): Result {
        StringBuilder().apply {
            append("Media content has changed:\n")
            params.triggeredContentAuthorities
                .takeIf { it.isNotEmpty() }
                ?.let { authorities ->
                    append("Authorities: ${authorities.joinToString(", ")}\n")
                    append(params.triggeredContentUris.joinToString("\n"))
                } ?: append("(No content)")
            Log.i(TAG, toString())
        }
        return Result.success()
    }
}

システム制限でアプリをテストする

アプリをメモリの少ないデバイスやメモリ不足の状態で実行するように最適化すると、パフォーマンスとユーザー エクスペリエンスが向上します。バックグラウンド サービスとマニフェストに登録された非明示的ブロードキャスト レシーバへの依存関係を削除すると、そのようなデバイスでのアプリの動作が改善されます。これらのバックグラウンド プロセスをまったく使用せずに、アプリを実行できるように最適化することをおすすめします。

その他の Android Debug Bridge(ADB)コマンドを使用すると、バックグラウンド プロセスを無効にしてアプリの動作をテストできます。

  • 非明示的ブロードキャストとバックグラウンド サービスが使用できない状況をシミュレートするには、次のコマンドを入力します。

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore

  • 非明示的ブロードキャストとバックグラウンド サービスを再度有効にするには、次のコマンドを入力します。

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow

アプリをさらに最適化する

バックグラウンド タスクの動作を最適化するその他の有効な方法については、タスク スケジューリング API のバッテリー使用量を最適化するのドキュメントをご覧ください。