Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

Cómo supervisar el nivel de batería y el estado de carga

Al modificar la frecuencia de las actualizaciones en segundo plano para reducir el efecto de estas en la duración de la batería, te recomendamos que comiences por comprobar el estado de carga y el nivel actual de la batería.

El impacto que tienen las actualizaciones de apps en la duración de la batería varía según el estado de carga y el nivel de la batería del dispositivo. Cuando el dispositivo está conectado a la corriente, el impacto es insignificante. Por lo tanto, en la mayoría de los casos, puedes maximizar la frecuencia de actualización cuando el dispositivo está conectado a un cargador de pared. Por el contrario, si el dispositivo está en proceso de descarga, disminuir la frecuencia de actualización te permitirá aumentar la duración de la batería.

Del mismo modo, puedes comprobar el nivel de carga de la batería y reducir la frecuencia de las actualizaciones (o incluso detenerlas) cuando la batería esté a punto de agotarse.

Cómo determinar el estado de carga actual

En primer lugar, determina el estado de carga actual. El BatteryManager transmite todos los detalles de carga y de la batería en un Intent persistente que incluye el estado de carga.

Como es un intent persistente, no necesitas registrar un BroadcastReceiver. Con solo llamar a registerReceiver y trasmitir null como el receptor (como se describe en el siguiente fragmento) se muestra el intent del estado actual de la batería. Aquí podrás transmitir un objeto BroadcastReceiver real, aunque no es necesario porque nos encargaremos de las actualizaciones en una próxima sección.

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

Puedes extraer el estado de carga actual y, si el dispositivo se está cargando, puedes ver si se está usando un cargador de CA o un USB.

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;
    

Por lo general, deberías maximizar la frecuencia de las actualizaciones en segundo plano cuando el dispositivo está conectado a un cargador de CA, disminuir esa frecuencia si se usa un cargador USB y reducirla aún más si la batería se está descargando.

Cómo supervisar los cambios en el estado de carga

El estado de carga puede modificarse muy fácilmente, por lo que es importante supervisarlo por si se producen cambios, y modificar la frecuencia de actualización según corresponda.

BatteryManager emite una acción cada vez que el dispositivo se conecta o desconecta de la corriente. Es importante que recibas estos eventos incluso cuando tu app no se está ejecutando (en especial porque estos pueden afectar la frecuencia con la que inicias tu app para ejecutar una actualización en segundo plano). Por lo tanto, deberías registrar un BroadcastReceiver en tu manifiesto para que escuche ambos eventos al definir ACTION_POWER_CONNECTED y ACTION_POWER_DISCONNECTED en un filtro de 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>

En la implementación de BroadcastReceiver asociada, puedes extraer el método y el estado de carga actual como se describe en el paso anterior.

Kotlin

    class PowerConnectionReceiver : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent) {
            val status: Int = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
            val isCharging: Boolean = status == BatteryManager.BATTERY_STATUS_CHARGING
                    || status == BatteryManager.BATTERY_STATUS_FULL

            val chargePlug: Int = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1)
            val usbCharge: Boolean = chargePlug == BatteryManager.BATTERY_PLUGGED_USB
            val acCharge: Boolean = chargePlug == BatteryManager.BATTERY_PLUGGED_AC
        }
    }
    

Java

    public class PowerConnectionReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
            boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                                status == BatteryManager.BATTERY_STATUS_FULL;

            int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
            boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
            boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
        }
    }
    

Cómo determinar el nivel de batería actual

En algunos casos, también es útil determinar el nivel de batería actual. Puedes disminuir la frecuencia de las actualizaciones en segundo plano si el nivel de carga de la batería es inferior a un valor determinado.

Para ver el nivel actual de batería, debes extraer la escala y el nivel de batería actual desde el intent de estado de la batería, como se muestra a continuación:

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 / scale.toFloat()
    }
    

Java

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

    float batteryPct = level / (float)scale;
    

Cómo supervisar cambios importantes en el nivel de la batería

No es fácil controlar continuamente el estado de la batería, pero tampoco es necesario.

En términos generales, verificar constantemente el nivel de batería afecta más el nivel de la batería que el comportamiento normal de tu app, por lo tanto, se recomienda solo supervisar los cambios importantes (en especial cuando el dispositivo entra o sale de un estado de carga bajo).

El fragmento de manifiesto que aparece a continuación se extrajo del elemento de filtro de intent de un receptor de emisión. El receptor se activa cada vez que el dispositivo entra o sale de un estado de carga bajo al escuchar ACTION_BATTERY_LOW y ACTION_BATTERY_OKAY.

    <receiver android:name=".BatteryLevelReceiver">
      <intent-filter>
        <action android:name="android.intent.action.BATTERY_LOW"/>
        <action android:name="android.intent.action.BATTERY_OKAY"/>
      </intent-filter>
    </receiver>

Cuando el nivel de batería esté demasiado bajo, te recomendamos que inhabilites las actualizaciones en segundo plano, ya que no importa qué tan actualizados estén los datos si el teléfono se apaga antes de que puedas usarlos.

En muchos casos, el hecho de cargar un dispositivo coincide con la acción de utilizar un conector. En la próxima lección, se explica cómo determinar el estado actual del conector y cómo supervisar los cambios que se producen al conectar el dispositivo.