I processi in background possono consumare memoria e batteria. Ad esempio, una trasmissione implicita può avviare molti processi in background che sono stati registrati per ascoltarla, anche se questi processi potrebbero non funzionare correttamente. Ciò può avere un impatto significativo sia sulle prestazioni del dispositivo sia sull'esperienza utente.
Per evitare limitazioni di sistema, assicurati di utilizzare l'API giusta per l'attività in background. La documentazione sulla panoramica delle attività in background ti aiuta a scegliere l'API giusta per le tue esigenze.
Limitazioni avviate dall'utente
Se un'app mostra alcune delle prestazioni scadenti descritte in Android vitals, il sistema chiede all'utente di limitare l'accesso dell'app alle risorse di sistema.
Se il sistema rileva un utilizzo eccessivo di risorse, avvisa l'utente e offre la possibilità di limitare le azioni dell'app. I comportamenti che possono attivare la notifica includono:
- Wakelock eccessivi: 1 wakelock parziale mantenuto per un'ora quando lo schermo è spento.
- Servizi in background eccessivi: se l'app ha come target livelli API inferiori a 26 e presenta servizi in background eccessivi
Le restrizioni precise imposte sono stabilite dal produttore del dispositivo. Ad esempio, nelle build AOSP, le app con limitazioni non possono eseguire job, attivare allarmi o utilizzare la rete, tranne quando l'app è in primo piano.
Limitazioni relative alla ricezione di trasmissioni delle attività di rete
Le app non ricevono broadcast CONNECTIVITY_ACTION
se si registrano per riceverli nel loro file manifest e i processi che dipendono da questa trasmissione non verranno avviati. Questo potrebbe rappresentare un problema per le app che vogliono rimanere in ascolto delle modifiche alla rete o eseguire attività di rete collettive quando il dispositivo si connette a una rete unmetered. Nel framework Android esistono già diverse soluzioni per aggirare questa limitazione, ma la scelta quella giusta dipende dall'obiettivo che vuoi far eseguire all'app.
Programma il lavoro sulle connessioni unmetere
Quando crei un WorkRequest
, aggiungi un Constraint
NetworkType.UNMETERED
.
fun scheduleWork(context: Context) {
val workManager = WorkManager.getInstance(context)
val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
)
.build()
workManager.enqueue(workRequest)
}
Quando le condizioni per il tuo lavoro sono soddisfatte, la tua app riceve un callback per eseguire
il metodo doWork()
nella classe Worker
specificata.
Monitorare la connettività di rete mentre l'app è in esecuzione
Le app in esecuzione possono comunque ascoltare CONNECTIVITY_CHANGE
con un BroadcastReceiver
registrato. Tuttavia, l'API ConnectivityManager
offre un metodo più affidabile per richiedere un callback solo quando sono soddisfatte le condizioni di rete specificate.
Gli oggetti NetworkRequest
definiscono i parametri del callback di rete in termini di NetworkCapabilities
. Per creare oggetti NetworkRequest
con la classe NetworkRequest.Builder
, registerNetworkCallback
quindi passa l'oggetto NetworkRequest
al sistema. Quando le condizioni di rete sono soddisfatte, l'app riceve un callback per eseguire il metodo onAvailable()
definito nella sua classe ConnectivityManager.NetworkCallback
.
L'app continua a ricevere callback fino a quando non esce dall'app o non chiama unregistraNetworkCallback().
Limitazioni relative alla ricezione di trasmissioni di immagini e video
Le app non sono in grado di inviare o ricevere trasmissioni ACTION_NEW_PICTURE o ACTION_NEW_VIDEO. Questa limitazione contribuisce a ridurre l'impatto sulle prestazioni e sull'esperienza utente quando è necessario attivare più app per elaborare una nuova immagine o un nuovo video.
Stabilire quali autorità di contenuti hanno attivato l'operatività
WorkerParameters
consente alla tua app di ricevere informazioni utili su quali URI e autorità dei contenuti hanno attivato l'operazione:
List<Uri> getTriggeredContentUris()
Restituisce un elenco di URI che hanno attivato l'elaborazione. Questo campo è vuoto se nessun URI ha attivato il lavoro (ad esempio se il lavoro è stato attivato a causa di una scadenza o per altri motivi) oppure se il numero di URI modificati è maggiore di 50.
List<String> getTriggeredContentAuthorities()
Restituisce un elenco di stringhe delle autorità di contenuto che hanno attivato l'operazione. Se
l'elenco restituito non è vuoto, utilizza getTriggeredContentUris()
per recuperare
i dettagli di quali URI sono stati modificati.
Il seguente codice campione esegue l'override del metodo CoroutineWorker.doWork()
e registra gli URI e le autorità di contenuti che hanno attivato il job:
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()
}
}
Testa l'app in base alle limitazioni di sistema
Se ottimizzi le tue app per eseguirle su dispositivi con memoria ridotta o in condizioni di scarsa memoria, puoi migliorare le prestazioni e l'esperienza utente. La rimozione delle dipendenze dai servizi in background e dai ricevitori di trasmissione impliciti registrati con manifest può consentire alla tua app di funzionare meglio su questi dispositivi. Ti consigliamo di ottimizzare l'app in modo che venga eseguita senza utilizzare questi processi in background.
Alcuni comandi Android Debug Bridge (ADB) aggiuntivi possono aiutarti a testare il comportamento dell'app quando i processi in background sono disabilitati:
Per simulare le condizioni in cui non sono disponibili trasmissioni implicite e servizi in background, inserisci il seguente comando:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore
Per riattivare le trasmissioni e i servizi in background impliciti, inserisci il seguente comando:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow
Ottimizza ulteriormente la tua app
Per altri modi efficaci per ottimizzare il comportamento delle attività in background, consulta la documentazione relativa all'ottimizzazione dell'utilizzo della batteria per le API di pianificazione delle attività.