监控电池电量和充电状态

当您调整后台更新频率以减少这些更新对电池续航时间的影响时,检查当前电池电量和充电状态是一个很好的开始。

执行应用更新对电池续航时间的影响取决于设备的电池电量和充电状态。在设备通过交流电源充电时执行更新的影响可以忽略不计,因此在大多数情况下,只要设备连接到墙壁充电器,您就可以最大化刷新率。反之,如果设备正在放电,降低更新频率有助于延长电池续航时间。

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

确定当前充电状态

首先确定当前的充电状态。BatteryManager 在一个黏性 Intent 中广播所有电池和充电详细信息,其中包含充电状态。

由于它是一个黏性 Intent,您无需注册 BroadcastReceiver——只需如以下代码片段所示,调用 registerReceiver 并传入 null 作为接收器,即可返回当前的电池状态 Intent。您可以在此处传入一个实际的 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 起已不可能)。相反,您可以为工作提供约束,描述其应何时运行,从而允许系统在不消耗电量启动应用的情况下做出决定。

通常,在电池电量严重不足时不要运行后台更新是一个好习惯。如果手机在您可以使用数据之前就关机了,那么您的数据有多新都无关紧要。为此,请使用 WorkManager 库,并带上 BatteryNotLow 约束,以指定当电池电量低时工作不应运行(除了任何相关的 NetworkType 约束)。

在许多情况下,设备充电的同时也会将其放入坞站。要了解更多信息,请参阅确定和监控坞接状态和类型