背景作業的系統限制

背景程序可能會耗用大量記憶體和電量。舉例來說 隱式廣播可能會啟動許多已註冊至 監聽模型,即使該程序可能執行了太多工作此功能可以 對裝置效能和使用者體驗造成重大影響。

為避免系統限制,請務必使用正確的 API 背景任務 背景工作總覽說明文件可協助您 以及符合自身需求的 API

使用者啟動限制

如果應用程式出現 Android Vitals 中描述的部分不良行為, 系統會提示使用者限制應用程式存取系統資源。

如果系統發現應用程式耗用過多資源,會發出通知 並提供選項讓使用者限制應用程式的動作。 可能觸發這類通知的行為包括:

  1. Wake Lock 過多:在螢幕關閉時,持續 1 小時的 1 個部分 Wake Lock 關閉
  2. 背景服務過多:如果應用程式指定的 API 級別低於 26 且背景服務過多

精確的限制項目由裝置製造商決定。適用對象 舉例來說,在 Android 開放原始碼計畫版本中,受限制的應用程式無法執行工作、觸發鬧鐘或使用 除非應用程式在前景執行。

接收網路活動廣播訊息的限制

如果應用程式已註冊 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() 方法。

在應用程式執行時監控網路連線

執行中的應用程式仍可透過CONNECTIVITY_CHANGE 已註冊 BroadcastReceiver,但 ConnectivityManager API 提供了更強大的方法,只有在指定網路時才要求回呼 條件相符。

NetworkRequest 物件會定義 NetworkCapabilities 的條款。您可以建立 NetworkRequest 物件 呼叫 NetworkRequest.Builder 類別。registerNetworkCallback敬上 然後將 NetworkRequest 物件傳遞至系統。連上網路後 如果符合條件,應用程式就會收到回呼,執行 onAvailable() 方法 ConnectivityManager.NetworkCallback 類別。

應用程式會持續收到回呼,直到應用程式結束或呼叫為止 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 的電池用量 說明文件。