Как отслеживать уровень заряда батареи и состояние зарядки

Если вы хотите изменить частоту фоновых обновлений, чтобы снизить их влияние на время работы от батареи, сначала проверьте текущий уровень заряда батареи и состояние зарядки.

Влияние обновлений приложений на время работы от батареи зависит от уровня заряда батареи и состояния зарядки устройства. Обновления, выполняемые во время зарядки устройства от сети переменного тока, практически не влияют на его работу, поэтому в большинстве случаев вы можете максимально увеличить частоту обновления, когда устройство подключено к зарядному устройству. И наоборот, если устройство разряжается, снижение частоты обновления помогает продлить срок службы батареи.

Аналогичным образом можно проверять уровень заряда батареи и снижать частоту обновлений или даже полностью их отключать, когда батарея почти разряжена.

Определить текущий статус зарядки

Сначала определите текущий статус оплаты. BatteryManager передает все сведения о батарее и зарядке в закрепленном Intent, которое включает статус зарядки.

Поскольку это закрепленное намерение, вам не нужно регистрировать BroadcastReceiver. Просто вызовите registerReceiver, передав null в качестве получателя, как показано в следующем фрагменте кода. Будет возвращено намерение текущего состояния батареи. Вы можете передать сюда фактический объект BroadcastReceiver, но мы будем обрабатывать обновления в следующем разделе, поэтому в этом нет необходимости.

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

Вы можете узнать текущий статус зарядки и, если устройство заряжается, способ зарядки (через 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;

Как правило, частота фоновых обновлений должна быть максимальной, когда устройство подключено к зарядному устройству переменного тока, снижаться при зарядке через USB и быть минимальной, когда батарея разряжается.

Отслеживание изменений в состоянии зарядки

Статус зарядки может измениться в любой момент, поэтому важно отслеживать его и соответствующим образом менять частоту обновления.

BatteryManager передает действие, когда устройство подключается к источнику питания или отключается от него. Важно получать эти события, даже когда приложение не запущено, поскольку они влияют на то, как часто вы запускаете приложение для фонового обновления. Поэтому вам следует зарегистрировать BroadcastReceiver в манифесте, чтобы прослушивать оба события, определив ACTION_POWER_CONNECTED и ACTION_POWER_DISCONNECTED в фильтре интентов.

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

Как узнать текущий уровень заряда батареи

В некоторых случаях также полезно определить текущий уровень заряда батареи. Вы можете снизить частоту фоновых обновлений, если заряд батареи ниже определенного уровня.

Чтобы узнать текущий уровень заряда батареи, извлеките его из намерения, как показано ниже:

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;

Реагировать на значительные изменения уровня заряда батареи

Постоянно следить за состоянием батареи не получится, но это и не нужно.

Как правило, отслеживание уровня заряда батареи оказывает большее влияние на батарею, чем обычное поведение вашего приложения. Например, если зарегистрировать в манифесте BroadcastReceiver, чтобы отменять ожидающие задачи при низком заряде батареи, это приведет к ещё большему ее разряду. Поэтому начиная с Android 8.0 такая возможность отсутствует. Вместо этого вы можете указать ограничения для работы, которые описывают, когда она должна быть запущена, позволяя системе принимать решение, не тратя энергию на запуск вашего приложения.

Рекомендуется не запускать фоновые обновления, когда заряд батареи критически низок. Неважно, насколько свежие у вас данные, если телефон выключится до того, как вы сможете ими воспользоваться. Для этого используйте библиотеку WorkManager с ограничением BatteryNotLow, чтобы указать, что задача не должна выполняться при низком уровне заряда батареи (в дополнение к любым другим ограничениям NetworkType).

Во многих случаях зарядка устройства совпадает с его установкой в док-станцию. Подробнее о том, как определить и отслеживать тип и состояние док-станции…