Monitorare il livello della batteria e lo stato di ricarica

Quando modifichi la frequenza degli aggiornamenti in background per ridurre l'effetto di questi aggiornamenti sulla durata della batteria, è consigliabile iniziare controllando il livello corrente della batteria e lo stato di ricarica.

L'impatto sulla durata della batteria dell'esecuzione degli aggiornamenti delle applicazioni dipende dal livello della batteria e dallo stato di ricarica del dispositivo. L'impatto degli aggiornamenti mentre il dispositivo è in carica tramite CA è trascurabile, quindi nella maggior parte dei casi puoi massimizzare la frequenza di aggiornamento ogni volta che il dispositivo è collegato a un caricabatterie da parete. Al contrario, se il dispositivo si sta scaricando, ridurre la frequenza di aggiornamento aiuta a prolungare la durata della batteria.

Analogamente, puoi controllare il livello di carica della batteria, potenzialmente riducendo la frequenza o persino interrompendo gli aggiornamenti quando la carica della batteria è quasi esaurita.

Determinare lo stato di ricarica attuale

Per prima cosa, determina lo stato attuale della ricarica. Il BatteryManager trasmette tutti i dettagli della batteria e della ricarica in un Intent fisso che include lo stato di ricarica.

Poiché si tratta di un intent fisso, non è necessario registrare un BroadcastReceiver: è sufficiente chiamare registerReceiver che passa in null come destinatario, come mostrato nel prossimo snippet, per restituire l'attuale intent relativo allo stato della batteria. Potresti passare un oggetto BroadcastReceiver effettivo qui, ma poiché gestiremo gli aggiornamenti in una sezione successiva, non è necessario.

Kotlin

val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
    context.registerReceiver(null, ifilter)
}

Java

IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = context.registerReceiver(null, ifilter);

Puoi estrarre sia lo stato di ricarica corrente sia, se il dispositivo è in carica, se sta ricaricando tramite caricabatterie USB o CA:

Kotlin

val status: Int = batteryStatus?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1
val isCharging: Boolean = status == BatteryManager.BATTERY_STATUS_CHARGING
        || status == BatteryManager.BATTERY_STATUS_FULL

// How are we charging?
val chargePlug: Int = batteryStatus?.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) ?: -1
val usbCharge: Boolean = chargePlug == BatteryManager.BATTERY_PLUGGED_USB
val acCharge: Boolean = chargePlug == BatteryManager.BATTERY_PLUGGED_AC

Java

// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                     status == BatteryManager.BATTERY_STATUS_FULL;

// How are we charging?
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;

In genere, dovresti massimizzare la frequenza degli aggiornamenti in background se il dispositivo è collegato a un caricabatterie CA, ridurla se la ricarica avviene tramite USB e abbassarla ulteriormente se la batteria si sta scaricando.

Monitora le variazioni dello stato di ricarica

Lo stato di ricarica può cambiare con la stessa facilità con cui colleghi un dispositivo, quindi è importante monitorare lo stato di ricarica per vedere eventuali cambiamenti e modificare la frequenza di aggiornamento di conseguenza.

BatteryManager trasmette un'azione ogni volta che il dispositivo è collegato o scollegato dall'alimentazione. È importante ricevere questi eventi anche quando l'app non è in esecuzione, soprattutto perché questi eventi dovrebbero influire sulla frequenza di avvio dell'app per avviare un aggiornamento in background, quindi devi registrare un BroadcastReceiver nel file manifest per ascoltare entrambi gli eventi definendo ACTION_POWER_CONNECTED e ACTION_POWER_DISCONNECTED all'interno di un filtro per intent.

<receiver android:name=".PowerConnectionReceiver">
  <intent-filter>
    <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
    <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
  </intent-filter>
</receiver>

Determina il livello attuale della batteria

In alcuni casi è utile anche determinare il livello attuale della batteria. Puoi scegliere di ridurre la frequenza degli aggiornamenti in background se il livello di carica della batteria è inferiore a un determinato livello.

Puoi trovare il livello di carica attuale della batteria estraendo il livello e la scala attuali dall'intent dello stato della batteria come mostrato qui:

Kotlin

val batteryPct: Float? = batteryStatus?.let { intent ->
    val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
    val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
    level * 100 / scale.toFloat()
}

Java

int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);

float batteryPct = level * 100 / (float)scale;

Reagire a variazioni significative del livello batteria

Non puoi monitorare facilmente e continuamente lo stato della batteria, ma non è necessario.

In generale, l'impatto del monitoraggio del livello della batteria sulla batteria è maggiore rispetto al normale comportamento dell'app. Ad esempio, la registrazione di un BroadcastReceiver nel file manifest per annullare il lavoro in attesa quando la batteria è in esaurimento servirà principalmente a scaricarla ulteriormente (e pertanto è impossibile da Android 8.0). Puoi invece fornire vincoli sul lavoro che descrivano quando eseguire l'app, in modo che il sistema possa prendere la decisione senza spendere potere all'avvio dell'app.

Generalmente è buona norma non eseguire aggiornamenti in background quando il livello della batteria è troppo basso. Non importa il livello di aggiornamento dei dati se lo smartphone si spegne prima che tu possa usarlo. Per farlo, utilizza la libreria WorkManager con un vincolo BatteryNotLow per specificare che il lavoro non deve essere eseguito se la batteria è in esaurimento (oltre a eventuali vincoli NetworkType pertinenti).

In molti casi, l'atto di ricaricare un dispositivo coincide con il suo inserimento in una base. Per scoprire di più, consulta Determinare e monitorare lo stato e il tipo di aggancio.