Hintergrundprozesse können speicher- und akkuintensiv sein. Beispielsweise kann eine implizite Broadcast-Nachricht viele Hintergrundprozesse starten, die sich für den Empfang dieser Nachricht registriert haben, auch wenn diese Prozesse nicht viel Arbeit verrichten. Dies kann sich erheblich auf die Geräteleistung und die Nutzerfreundlichkeit auswirken.
Verwenden Sie die richtige API für Ihre Hintergrundaufgabe, um Systembeschränkungen zu vermeiden. In der Dokumentation Übersicht über Hintergrundaufgaben finden Sie Informationen zur Auswahl der richtigen API für Ihre Anforderungen.
Von Nutzern initiierte Einschränkungen
Wenn eine App einige der in Android Vitals beschriebenen schlechten Verhaltensweisen aufweist, fordert das System den Nutzer auf, den Zugriff dieser App auf Systemressourcen einzuschränken.
Wenn das System feststellt, dass eine App übermäßig viele Ressourcen verbraucht, wird der Nutzer benachrichtigt und hat die Möglichkeit, die Aktionen der App einzuschränken. Folgende Verhaltensweisen können diese Benachrichtigung auslösen:
- Übermäßige Wakelocks: 1 Teil-Wakelock wird eine Stunde lang gehalten, wenn der Bildschirm ausgeschaltet ist.
- Übermäßige Hintergrunddienste: Wenn die App auf API-Ebenen unter 26 ausgerichtet ist und übermäßig viele Hintergrunddienste verwendet
Die genauen Einschränkungen werden vom Gerätehersteller festgelegt. Bei AOSP-Builds können eingeschränkte Apps beispielsweise keine Jobs ausführen, keine Alarme auslösen und das Netzwerk nicht verwenden, es sei denn, die App befindet sich im Vordergrund.
Einschränkungen beim Empfang von Broadcast-Nachrichten zu Netzwerkaktivitäten
Apps empfangen keine CONNECTIVITY_ACTION-Broadcast-Nachrichten, wenn sie sich in ihrem Manifest für den Empfang registrieren. Prozesse, die von dieser Broadcast-Nachricht abhängen, werden nicht gestartet. Dies kann ein Problem für Apps darstellen, die auf Netzwerkänderungen warten oder Netzwerkaktivitäten im Bulk ausführen möchten, wenn das Gerät mit einem Netzwerk ohne Datenlimit verbunden ist. Im Android-Framework gibt es bereits mehrere Lösungen, um diese Einschränkung zu umgehen. Die Auswahl der richtigen Lösung hängt jedoch davon ab, was Ihre App erreichen soll.
Aufgaben für Verbindungen ohne Datenlimit planen
Fügen Sie beim Erstellen eines WorkRequest eine NetworkType.UNMETERED-Constraint hinzu.
fun scheduleWork(context: Context) {
val workManager = WorkManager.getInstance(context)
val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
)
.build()
workManager.enqueue(workRequest)
}
Wenn die Bedingungen für Ihre Aufgabe erfüllt sind, erhält Ihre App einen Callback, um
die doWork() Methode in der angegebenen Worker Klasse auszuführen.
Netzwerkverbindung überwachen, während die App ausgeführt wird
Apps, die ausgeführt werden, können weiterhin auf CONNECTIVITY_CHANGE warten, wenn ein
registrierter BroadcastReceiver registriert ist. Die ConnectivityManager-API
bietet jedoch eine robustere Methode, um einen Callback nur anzufordern, wenn bestimmte Netzwerk
bedingungen erfüllt sind.
NetworkRequest-Objekte definieren die Parameter des Netzwerk-Callbacks in
Bezug auf NetworkCapabilities. Sie erstellen NetworkRequest-Objekte
mit der Klasse NetworkRequest.Builder. registerNetworkCallback
übergibt das NetworkRequest-Objekt dann an das System. Wenn die Netzwerkbedingungen erfüllt sind, erhält die App einen Callback, um die
onAvailable() Methode auszuführen, die in der
ConnectivityManager.NetworkCallback Klasse definiert ist.
Die App erhält weiterhin Callbacks, bis sie beendet wird oder unregisterNetworkCallback() aufgerufen wird.
Einschränkungen beim Empfang von Broadcast-Nachrichten zu Bildern und Videos
Apps können keine ACTION_NEW_PICTURE- oder ACTION_NEW_VIDEO-Broadcast-Nachrichten senden oder empfangen. Diese Einschränkung trägt dazu bei, die Auswirkungen auf die Leistung und die Nutzerfreundlichkeit zu verringern, wenn mehrere Apps aktiviert werden müssen, um ein neues Bild oder Video zu verarbeiten.
Bestimmen, welche Content-Provider die Aufgabe ausgelöst haben
WorkerParameters ermöglicht Ihrer App, nützliche Informationen dazu zu erhalten, welche
Content-Provider und URIs die Aufgabe ausgelöst haben:
List<Uri> getTriggeredContentUris()
Gibt eine Liste von URIs zurück, die die Aufgabe ausgelöst haben. Diese Liste ist leer, wenn entweder keine URIs die Aufgabe ausgelöst haben (z. B. wurde die Aufgabe aufgrund einer Frist oder aus einem anderen Grund ausgelöst) oder die Anzahl der geänderten URIs größer als 50 ist.
List<String> getTriggeredContentAuthorities()
Gibt eine Stringliste von Content-Providern zurück, die die Aufgabe ausgelöst haben. Wenn die zurückgegebene Liste nicht leer ist, verwenden Sie getTriggeredContentUris(), um die Details der geänderten URIs abzurufen.
Im folgenden Beispielcode wird die CoroutineWorker.doWork() Methode überschrieben und die Content-Provider und URIs aufgezeichnet, die die Aufgabe ausgelöst haben:
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()
}
}
App unter Systembeschränkungen testen
Wenn Sie Ihre Apps für die Ausführung auf Geräten mit wenig Arbeitsspeicher oder unter Bedingungen mit wenig Arbeitsspeicher optimieren, können Sie die Leistung und die Nutzerfreundlichkeit verbessern. Wenn Sie Abhängigkeiten von Hintergrunddiensten und im Manifest registrierten impliziten Broadcast-Empfängern entfernen, kann Ihre App auf solchen Geräten besser ausgeführt werden. Es wird empfohlen, Ihre App so zu optimieren, dass sie vollständig ohne diese Hintergrundprozesse ausgeführt werden kann.
Mit einigen zusätzlichen Android Debug Bridge-Befehlen (ADB) können Sie das App-Verhalten testen, wenn diese Hintergrundprozesse deaktiviert sind:
Geben Sie den folgenden Befehl ein, um Bedingungen zu simulieren, unter denen implizite Broadcast-Nachrichten und Hintergrunddienste nicht verfügbar sind:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignoreGeben Sie den folgenden Befehl ein, um implizite Broadcast-Nachrichten und Hintergrunddienste wieder zu aktivieren:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow
App weiter optimieren
Weitere gute Möglichkeiten zur Optimierung des Verhaltens Ihrer Hintergrundaufgaben finden Sie in der Dokumentation Akkunutzung für APIs zur Aufgabenplanung optimieren.