Surveiller l'état de charge et le niveau de la batterie

Lorsque vous modifiez la fréquence de vos mises à jour en arrière-plan pour réduire l'effet de ces mises à jour sur l'autonomie de la batterie, il est judicieux de vérifier le niveau actuel de la batterie et l'état de charge.

L'impact sur l'autonomie de la batterie des mises à jour d'applications dépend du niveau de la batterie et de l'état de charge de l'appareil. L'impact des mises à jour lorsque l'appareil est en charge sur secteur est négligeable. Dans la plupart des cas, vous pouvez donc maximiser la fréquence d'actualisation lorsque l'appareil est connecté à un chargeur mural. À l'inverse, si l'appareil se décharge, réduire la fréquence de mise à jour permet de prolonger l'autonomie de la batterie.

De même, vous pouvez vérifier le niveau de charge de la batterie, ce qui peut réduire la fréquence, voire l'arrêt, de vos mises à jour lorsque la charge de la batterie est presque épuisée.

Déterminer l'état de charge actuel

Commencez par déterminer l'état de charge actuel. BatteryManager diffuse toutes les informations sur la batterie et la charge dans un Intent persistant qui inclut l'état de charge.

Comme il s'agit d'un intent persistant, vous n'avez pas besoin d'enregistrer un BroadcastReceiver. Il suffit d'appeler registerReceiver en transmettant null en tant que récepteur, comme indiqué dans l'extrait suivant, l'intent d'état actuel de la batterie est renvoyé. Vous pouvez transmettre un objet BroadcastReceiver réel ici, mais nous traiterons les mises à jour dans une section ultérieure. Ce n'est donc pas nécessaire.

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);

Vous pouvez extraire à la fois l'état de charge actuel et, si l'appareil est en cours de charge, s'il est en charge via USB ou un chargeur:

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;

En règle générale, vous devez optimiser le taux de mises à jour en arrière-plan lorsque l'appareil est connecté à un chargeur secteur, réduire le taux si la charge est via USB et le réduire davantage si la batterie se décharge.

Surveiller les changements de l'état de charge

L'état de charge peut changer aussi facilement qu'un appareil peut être branché. Il est donc important de surveiller l'état de charge pour détecter les changements et de modifier votre fréquence d'actualisation en conséquence.

Le BatteryManager diffuse une action chaque fois que l'appareil est connecté ou débranché de l'alimentation. Il est important de recevoir ces événements même lorsque votre application n'est pas en cours d'exécution, car ils doivent avoir un impact sur la fréquence à laquelle vous la démarrez pour lancer une mise à jour en arrière-plan. Vous devez donc enregistrer un BroadcastReceiver dans votre fichier manifeste pour écouter les deux événements en définissant ACTION_POWER_CONNECTED et ACTION_POWER_DISCONNECTED dans un filtre d'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>

Déterminer le niveau actuel de la batterie

Dans certains cas, il est également utile de déterminer le niveau actuel de la batterie. Vous pouvez choisir de réduire la fréquence des mises à jour en arrière-plan si la charge de la batterie est inférieure à un certain niveau.

Pour déterminer la charge actuelle de la batterie, extrayez le niveau et l'échelle actuels de la batterie à partir de l'intent d'état de la batterie, comme indiqué ci-dessous:

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;

Réagir à des changements importants du niveau de la batterie

Vous ne pouvez pas facilement surveiller en permanence l'état de la batterie, mais cela n'est pas nécessaire.

De manière générale, la surveillance du niveau de la batterie a un impact plus important sur celle-ci que le comportement normal de votre application. Par exemple, l'enregistrement d'un BroadcastReceiver dans le fichier manifeste pour annuler une tâche en attente lorsque la batterie est faible sert principalement à la décharger davantage (ce qui est impossible depuis Android 8.0). À la place, vous pouvez fournir des contraintes sur les tâches qui décrivent le moment où elles doivent être exécutées, ce qui permet au système de prendre une décision sans dépenser d'énergie au démarrage de votre application.

Il est généralement recommandé de ne pas exécuter les mises à jour en arrière-plan lorsque la batterie est très faible. Peu importe la fraîcheur de vos données si le téléphone s'éteint avant que vous ne puissiez les utiliser. Pour ce faire, utilisez la bibliothèque WorkManager avec une contrainte BatteryNotLow afin de spécifier que la tâche ne doit pas être exécutée si la batterie est faible (en plus des contraintes NetworkType pertinentes).

Dans de nombreux cas, le fait de charger un appareil coïncide avec le fait de le placer sur une station d'accueil. La leçon suivante vous explique comment déterminer l'état actuel de la station d'accueil et surveiller les modifications apportées à la station d'accueil.