背景程序可能會耗用大量記憶體和電量。舉例來說 隱式廣播可能會啟動許多已註冊至 監聽模型,即使該程序可能執行了太多工作此功能可以 對裝置效能和使用者體驗造成重大影響。
為避免系統限制,請務必使用正確的 API 背景任務 背景工作總覽說明文件可協助您 以及符合自身需求的 API
使用者啟動限制
如果應用程式出現 Android Vitals 中描述的部分不良行為, 系統會提示使用者限制應用程式存取系統資源。
如果系統發現應用程式耗用過多資源,會發出通知 並提供選項讓使用者限制應用程式的動作。 可能觸發這類通知的行為包括:
- Wake Lock 過多:在螢幕關閉時,持續 1 小時的 1 個部分 Wake Lock 關閉
- 背景服務過多:如果應用程式指定的 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 的電池用量 說明文件。