Ottimizza posizione per batteria

I Limiti di località in background introdotti in Android 8.0 (livello API 26) hanno rinnovato l'attenzione sul modo in cui l'utilizzo dei servizi di geolocalizzazione influisce sul consumo della batteria. In questa pagina vengono descritte alcune best practice relative ai servizi di geolocalizzazione e cosa puoi fare ora per aumentare l'efficienza della batteria delle tue app. L'applicazione di queste best practice va a vantaggio della tua app a prescindere dalla versione della piattaforma su cui viene eseguita.

I limiti di posizione in background di Android 8.0 hanno introdotto le seguenti modifiche:

  • La raccolta della posizione in background viene limitata e la località viene calcolata e recapitata solo poche volte all'ora.
  • Le ricerche di reti Wi-Fi sono più prudenti e gli aggiornamenti della posizione non vengono calcolati quando il dispositivo rimane connesso allo stesso punto di accesso statico.
  • La reattività del geofencing cambia da decine di secondi a circa due minuti. Questa modifica migliora notevolmente le prestazioni della batteria, fino a 10 volte migliore su alcuni dispositivi.

Questa pagina presuppone l'utilizzo delle API dei servizi di geolocalizzazione di Google, che offrono una maggiore precisione e comportano un carico più leggero della batteria rispetto alle API di località framework. In particolare, questa pagina presuppone familiarità con l'API del provider di localizzazione, che combina segnali provenienti da GPS, Wi-Fi e reti cellulari, nonché accelerometro, giroscopio, magnetometro e altri sensori. Dovresti anche avere familiarità con l'API geofencing, che si basa sull'API fused location provider ed è ottimizzata per le prestazioni della batteria.

Informazioni sul consumo eccessivo della batteria

La raccolta della posizione e il consumo eccessivo della batteria sono direttamente correlati ai seguenti aspetti:

  • Precisione: la precisione dei dati sulla posizione. In generale, maggiore è la precisione, più elevato è il consumo della batteria.
  • Frequenza: la frequenza di calcolo della località. Più viene calcolata la posizione, maggiore è il consumo di batteria.
  • Latenza: la velocità di consegna dei dati sulla posizione. Una minore latenza di solito richiede più batteria.

Precisione

Puoi specificare la precisione della posizione utilizzando il metodo setPriority(), passando uno dei seguenti valori come argomento:

  • PRIORITY_HIGH_ACCURACY fornisce la posizione più precisa possibile, che viene calcolata utilizzando il numero massimo di input necessario (abilita GPS, Wi-Fi e cellulare e utilizza una serie di sensori) e può comportare un consumo significativo della batteria.
  • PRIORITY_BALANCED_POWER_ACCURACY fornisce una posizione precisa, ottimizzando al contempo la potenza. Molto raramente utilizza il GPS. In genere utilizza una combinazione di informazioni Wi-Fi e cellulare per calcolare la posizione del dispositivo.
  • PRIORITY_LOW_POWER si basa principalmente sulle torri cellulari ed evita gli input GPS e Wi-Fi, fornendo una precisione approssimativa (a livello di città) con un consumo minimo della batteria.
  • PRIORITY_NO_POWER riceve le posizioni passivamente da altre app per le quali la località è già stata calcolata.

Le esigenze di geolocalizzazione della maggior parte delle app possono essere soddisfatte utilizzando le opzioni di alimentazione bilanciata o a basso consumo. L'alta precisione dovrebbe essere riservata alle app in esecuzione in primo piano e che richiedono aggiornamenti della posizione in tempo reale (ad esempio, un'app di mappatura).

Frequenza

Puoi specificare la frequenza della località utilizzando due metodi:

  • Utilizza il metodo setinterval() per specificare l'intervallo con cui viene calcolata la località per la tua app.
  • Utilizza setFastestInterval() per specificare l'intervallo con cui la località calcolata per altre app viene pubblicata nella tua app.

Devi trasmettere il valore più elevato possibile quando utilizzi setInterval(). Questo è particolarmente vero per la raccolta della posizione in background, che spesso causa un consumo indesiderato della batteria. L'uso di intervalli di pochi secondi dovrebbe essere prenotato per i casi d'uso in primo piano. I limiti di posizione in background introdotti in Android 8.0 applicano queste strategie, ma la tua app deve cercare di applicarli su dispositivi Android 7.0 o versioni precedenti.

Latenza

Puoi specificare la latenza utilizzando il metodo setMaxWaitTime(), passando in genere un valore diverse volte superiore all'intervallo specificato nel metodo setInterval(). Questa impostazione ritarda la consegna delle località e più aggiornamenti della località potrebbero essere inviati in batch. Queste due modifiche aiutano a ridurre al minimo il consumo della batteria.

Se la tua app non ha bisogno di un aggiornamento della posizione immediatamente, devi passare il valore più alto possibile al metodo setMaxWaitTime(), scambiando la latenza per ottenere più dati e aumentare l'efficienza della batteria.

Quando utilizzi recinti virtuali, le app devono trasferire un valore elevato al metodo setNotificationResponsiveness() per preservare l'alimentazione. Si consiglia un valore di almeno cinque minuti.

Casi d'uso della località

In questa sezione vengono descritti alcuni scenari tipici di raccolta della località, insieme ad alcuni consigli per l'uso ottimale delle API del provider di località geografica e delle relative API.

Aggiornamenti visibili all'utente o in primo piano

Esempio: un'app di mappatura che richiede aggiornamenti frequenti e accurati con latenza molto bassa. Tutti gli aggiornamenti vengono eseguiti in primo piano: l'utente avvia un'attività, consuma i dati sulla posizione e poi interrompe l'attività dopo un breve periodo di tempo.

Utilizza il metodo setPriority() con un valore di PRIORITY_HIGH_ACCURACY o PRIORITY_BALANCED_POWER_ACCURACY.

L'intervallo specificato nel metodo setInterval() dipende dal caso d'uso: per scenari in tempo reale, imposta il valore su pochi secondi; in caso contrario, limitalo a pochi minuti (è consigliato un intervallo di circa due minuti o maggiore per ridurre al minimo l'utilizzo della batteria).

Conoscere la posizione del dispositivo

Esempio: un'app meteo vuole conoscere la posizione del dispositivo.

Utilizza il metodo getLastLocation(), che restituisce la località disponibile più di recente (che in rari casi potrebbe essere nulla) . Questo metodo offre un modo semplice per ottenere la posizione e non prevede costi associati alla richiesta attiva di aggiornamenti della posizione. Da utilizzare insieme al metodo isLocationAvailable(), che restituisce true quando la località restituita da getLastLocation() è ragionevolmente aggiornata.

Avvio degli aggiornamenti quando un utente si trova in una località specifica

Esempio: richiedere aggiornamenti quando un utente si trova entro una determinata distanza da casa, dal lavoro o da un'altra località.

Utilizza il geofencing in combinazione con gli aggiornamenti dei provider di località combinati. Richiedi gli aggiornamenti quando l'app riceve un attivatore di accesso al recinto virtuale e rimuovi gli aggiornamenti quando riceve un attivatore di uscita del recinto virtuale. In questo modo, l'app riceve aggiornamenti della posizione più granulari solo quando l'utente entra in un'area definita.

Il flusso di lavoro tipico per questo scenario potrebbe comportare la visualizzazione di una notifica quando l'ingresso del recinto virtuale è attivo e l'avvio di un'attività che contiene il codice per richiedere aggiornamenti quando l'utente tocca la notifica.

Avvio degli aggiornamenti in base allo stato dell'attività dell'utente

Esempio: richiedere aggiornamenti solo quando l'utente guida o è in bicicletta.

Utilizza l'API Activity Recognition insieme agli aggiornamenti fusi del provider di località. Richiedere aggiornamenti quando viene rilevata l'attività target e rimuovere gli aggiornamenti quando l'utente smette di eseguire l'attività in questione.

Il flusso di lavoro tipico per questo caso d'uso potrebbe prevedere la visualizzazione di una notifica per l'attività rilevata e l'avvio di un'attività che contiene codice per richiedere aggiornamenti quando l'utente tocca la notifica.

Aggiornamenti a lungo termine della posizione in background relativi alle aree geografiche

Esempio: l'utente vuole ricevere una notifica quando il dispositivo si trova nelle vicinanze di un rivenditore.

Si tratta di un ottimo caso d'uso per il geofencing. Poiché il caso d'uso riguarda quasi certamente la posizione in background, utilizza il metodo addGeofences(GeofencingRequest, PendingIntent).

Dovresti impostare le seguenti opzioni di configurazione:

  • Se monitori le transizioni di interazione, utilizza il metodo setLoiteringDelay() per trasmettere un valore di circa cinque minuti o meno.

  • Utilizza il setNotificationResponsiveness(), trasmettendo un valore di circa cinque minuti. Tuttavia, ti consigliamo di utilizzare un valore di circa dieci minuti se la tua app è in grado di gestire il ritardo aggiuntivo di reattività.

Un'app può registrare un massimo di 100 recinti virtuali alla volta. In un caso d'uso in cui un'app voglia monitorare un numero elevato di opzioni di rivenditori, l'app potrebbe voler registrare un recinto virtuale di grandi dimensioni (a livello di città) e registrare dinamicamente recinti virtuali più piccoli (per località all'interno della città) per i negozi all'interno del recinto virtuale più grande. Quando l'utente accede a un recinto virtuale di grandi dimensioni, è possibile aggiungere recinzioni geografiche più piccole; quando l'utente esce dal recinto virtuale più grande, è possibile rimuovere i recinzioni geografici più piccoli e registrare nuovamente i recinzioni virtuali per una nuova area.

Aggiornamenti a lunga esecuzione della posizione in background senza un componente dell'app visibile

Esempio: un'app che monitora passivamente la posizione

Se possibile, utilizza il metodo setPriority() con l'opzione PRIORITY_NO_POWER perché non consuma quasi la batteria. Se non è possibile usare PRIORITY_NO_POWER, usa PRIORITY_BALANCED_POWER_ACCURACY o PRIORITY_LOW_POWER, ma evita di utilizzare PRIORITY_HIGH_ACCURACY per attività prolungate in background perché questa opzione scarica notevolmente la batteria.

Se hai bisogno di più dati sulla posizione, utilizza la posizione passiva chiamando il metodo setFastestInterval() trasmettendo un valore inferiore a quello passato a setInterval(). Se combinata con l'opzione PRIORITY_NO_POWER, la posizione passiva può fornire a seconda delle esigenze la posizione calcolata da altre app senza costi aggiuntivi.

Modera la frequenza aggiungendo un po' di latenza, utilizzando il metodo setMaxWaitTime(). Ad esempio, se utilizzi il metodo setinterval() con un valore di circa 10 minuti, ti consigliamo di chiamare setMaxWaitTime() con un valore compreso tra 30 e 60 minuti. Con queste opzioni, la posizione della tua app viene calcolata ogni 10 minuti circa, ma l'app viene attivata solo ogni 30-60 minuti con alcuni dati sulla posizione disponibili come aggiornamento batch. Questo approccio scambia la latenza per ottenere più dati disponibili e migliori prestazioni della batteria.

Aggiornamenti frequenti ad alta precisione mentre l'utente interagisce con altre app

Esempio: un'app di navigazione o fitness che continua a funzionare quando l'utente spegne lo schermo o apre un'altra app.

Utilizza un servizio in primo piano. Se la tua app potrebbe svolgere attività costose per conto dell'utente, è consigliabile informare l'utente di tale operazione. Un servizio in primo piano richiede una notifica permanente. Per ulteriori informazioni, vedi Panoramica delle notifiche.

Best practice relative alla località

L'implementazione delle best practice in questa sezione aiuta a ridurre l'utilizzo della batteria da parte della tua app.

Rimuovere gli aggiornamenti della posizione

Una fonte comune di consumo eccessivo della batteria è la mancata rimozione degli aggiornamenti della posizione quando non sono più necessari. Questo può accadere, ad esempio, quando i metodi del ciclo di vita di un'attività onStart() o onResume() contengono una chiamata a requestlocationUpdates() senza una chiamata corrispondente a removeLocationUpdates() nei metodi del ciclo di vita onPause() o onStop().

Puoi utilizzare i componenti sensibili al ciclo di vita per gestire meglio il ciclo di vita delle attività nella tua app. Per ulteriori informazioni, consulta Gestione dei cicli di vita con componenti sensibili al ciclo di vita.

Imposta timeout

Per evitare il consumo eccessivo della batteria, imposta un timeout ragionevole quando gli aggiornamenti della posizione devono essere interrotti. Il timeout garantisce che gli aggiornamenti non proseguano a tempo indeterminato e protegge l'app in scenari in cui gli aggiornamenti vengono richiesti ma non rimossi (ad esempio a causa di un bug nel codice).

Per una richiesta di provider di località fusa, aggiungi un timeout chiamando setExpirationDuration(), che riceve un parametro che rappresenta il tempo in millisecondi dall'ultima chiamata del metodo. Puoi anche aggiungere un timeout chiamando setExpirationTime(), che riceve un parametro che rappresenta la scadenza in millisecondi dall'ultimo avvio del sistema.

Per aggiungere un timeout a una richiesta di posizione del recinto virtuale, chiama il metodo setExpirationDuration().

Richieste batch

Per tutti i casi d'uso non in primo piano, raggruppa più richieste. Puoi utilizzare il metodo setInterval() per specificare l'intervallo con cui vuoi che venga calcolata la località. Quindi, utilizza il metodo setMaxWaitTime() per impostare l'intervallo di pubblicazione della località per la tua app. Il valore trasmesso al metodo setMaxWaitTime() deve essere un multiplo del valore passato al metodo setInterval(). Ad esempio, considera la seguente richiesta di posizione:

Kotlin

val request = LocationRequest()
request.setInterval(10 * 60 * 1000)
request.setMaxWaitTime(60 * 60 * 1000)

Java

LocationRequest request = new LocationRequest();
request.setInterval(10 * 60 * 1000);
request.setMaxWaitTime(60 * 60 * 1000);

In questo caso, la località viene calcolata circa ogni dieci minuti e circa sei punti dati della località vengono pubblicati in un batch ogni ora circa. Anche se continui a ricevere aggiornamenti sulla posizione ogni dieci minuti circa, risparmi la batteria perché il dispositivo viene svegliato solo ogni ora circa.

Utilizzare gli aggiornamenti passivi della posizione

Nei casi d'uso in background, è consigliabile limitare gli aggiornamenti della posizione. I limiti di Android 8.0 applicano questa pratica, ma le app in esecuzione su dispositivi meno recenti dovrebbero cercare di limitare il più possibile la posizione in background.

È probabile che mentre la tua app è in background, un'altra app potrebbe richiedere spesso aggiornamenti della posizione in primo piano. I servizi di geolocalizzazione rendono disponibili questi aggiornamenti per la tua app. Considera la seguente richiesta di posizione, che utilizza i dati sulla posizione in modo opportuno:

Kotlin

val request = LocationRequest()
request.setInterval(15 * 60 * 1000)
request.setFastestInterval(2 * 60 * 1000)

Java

LocationRequest request = new LocationRequest();
request.setInterval(15 * 60 * 1000);
request.setFastestInterval(2 * 60 * 1000);

Nell'esempio precedente, la località per l'app viene calcolata ogni 15 minuti circa. Se altre app richiedono la posizione, i dati vengono resi disponibili per la tua app a un intervallo massimo di due minuti.

Anche se il consumo passivo della posizione non comporta alcun consumo passivo della batteria, presta particolare attenzione nei casi in cui la ricezione dei dati sulla posizione attivi operazioni costose della CPU o di I/O. Per ridurre al minimo i costi della batteria, l'intervallo specificato in setFastestInterval() non deve essere troppo piccolo.

Puoi migliorare notevolmente le prestazioni della batteria dei dispositivi dei tuoi utenti seguendo i consigli in questa pagina. È meno probabile che gli utenti eliminino le app che non consumano la batteria.