Monitorare il livello della batteria e lo stato di ricarica

Quando modifichi la frequenza degli aggiornamenti in background per ridurre gli effetti di tali aggiornamenti sulla durata della batteria, controllare il livello attuale della batteria e lo stato di ricarica è un ottimo punto di partenza.

L'impatto sulla durata della batteria 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 caricabatteria a parete. Al contrario, se il dispositivo si sta scaricando, ridurre la frequenza di aggiornamento contribuisce a prolungare la durata della batteria.

Analogamente, puoi controllare il livello di carica della batteria, riducendo potenzialmente la frequenza o addirittura l'interruzione degli aggiornamenti quando la carica della batteria è quasi esaurita.

Determinare lo stato di ricarica attuale

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

Poiché si tratta di un intent fisso, non è necessario registrare un BroadcastReceiver: è sufficiente chiamare registerReceiver che trasmette null come destinatario, come mostrato nello snippet successivo, per restituire l'intent attuale dello stato della batteria. Puoi passare un oggetto BroadcastReceiver reale qui, ma gli aggiornamenti verranno gestiti in una sezione successiva, quindi 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 carica attuale sia, se il dispositivo è in carica, se è in carica tramite USB o caricabatterie 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 velocità degli aggiornamenti in background nel caso in cui il dispositivo sia collegato a un caricabatterie CA, ridurla se la ricarica è tramite USB e abbassarla ulteriormente se la batteria si sta scaricando.

Monitorare le variazioni dello stato di ricarica

Lo stato di ricarica può cambiare con la stessa facilità con cui è possibile collegare un dispositivo, perciò è importante monitorare lo stato di ricarica per 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, in particolare perché dovrebbero influire sulla frequenza con cui avvii l'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 in 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>

Determinare 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 attuale della batteria e scalando 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;

Reagisci a cambiamenti significativi del livello della batteria

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

In generale, l'impatto del monitoraggio del livello della batteria ha un impatto 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 il livello della batteria è basso servirà principalmente a scaricare ulteriormente la batteria (ed è quindi impossibile a partire da Android 8.0). Puoi invece fornire dei vincoli sul lavoro che descrivono quando deve essere eseguita, consentendo al sistema di prendere una decisione senza spendere energia per avviare l'app.

È buona norma non eseguire aggiornamenti in background quando il livello della batteria è molto basso. Non importa quanto siano aggiornati i dati se il telefono si spegne prima che tu possa usarli. A questo scopo, utilizza la libreria di WorkManager con un vincolo BatteryNotLow per specificare che il lavoro non deve essere eseguito quando il livello della batteria è basso (oltre a eventuali vincoli NetworkType pertinenti).

In molti casi, la ricarica di un dispositivo coincide con l'inserimento nel dock. La prossima lezione ti mostra come determinare lo stato attuale del dock e monitorare le modifiche nel dock del dispositivo.