监控电池电量和充电状态

当您更改后台更新的频率以减少这些更新对电池寿命的影响时,检查当前电池电量和充电状态是一个不错的起点。

执行应用更新对电池寿命的影响取决于设备的电池电量和充电状态。在大多数情况下,当设备连接到墙上充电器时,您可以最大化刷新率,因为在设备充电时执行更新对电池的影响可以忽略不计。相反,如果设备正在放电,降低更新速率有助于延长电池寿命。

同样,您可以检查电池电量,当电池电量几乎耗尽时,可能会降低或甚至停止更新频率。

确定当前充电状态

首先确定当前充电状态。 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_CONNECTEDACTION_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起已不可行)。相反,您可以对工作设置约束来描述何时应运行工作,允许系统在不耗费启动应用的电量的情况下做出决策。

通常情况下,当电池电量极低时,不运行后台更新是一个好习惯。如果手机在您能够使用数据之前就自行关机了,那么您的数据有多新都无关紧要。为此,请使用带BatteryNotLow约束WorkManager库来指定,如果电池电量低(以及任何相关的NetworkType约束),则不应运行该工作。

在许多情况下,为设备充电与将其放入底座是同时发生的。要了解更多信息,请参阅确定并监控底座状态和类型