電池残量と充電状態を監視する

バックグラウンド更新の頻度を変更して電池寿命への影響を抑える場合は、まず現在の電池残量と充電状態を確認することをおすすめします。

アプリケーション アップデートの実行によるバッテリー駆動時間への影響は、デバイスのバッテリー残量と充電状態によって異なります。デバイスが AC で充電されている間にアップデートを実行しても影響はごくわずかです。そのため、ほとんどの場合、デバイスが壁の充電器に接続されているときはリフレッシュ レートを最大化できます。逆に、デバイスが放電している場合は、アップデート レートを下げるとバッテリー寿命を延ばすことができます。

同様に、バッテリーの充電レベルを確認することで、バッテリーの充電がほぼ枯渇したときに、アップデートの頻度を減らしたり、アップデートを停止したりできるようになります。

現在の充電状態を特定する

初めに現在の充電状態を特定します。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 または AC 充電器)の両方を抽出できます。

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;

一般に、バックグラウンド更新のレートは、デバイスが AC 充電器に接続されている場合は最大化し、USB 経由で充電する場合はレートを減らし、バッテリーが放電している場合はさらに下げます。

充電状態の変化を監視する

充電ステータスは、デバイスを電源に接続するのと同じくらい簡単に変化する可能性があるため、充電状態の変化をモニタリングし、それに応じてリフレッシュ レートを変更することが重要です。

BatteryManager は、デバイスの電源接続または切断時にアクションをブロードキャストします。アプリが実行中でなくても、こうしたイベントを受け取ることが重要です。特に、これらのイベントはバックグラウンド アップデートを開始するためにアプリを起動する頻度に影響するため、インテント フィルタ内で ACTION_POWER_CONNECTEDACTION_POWER_DISCONNECTED を定義して、両方のイベントをリッスンするためにマニフェストに BroadcastReceiver を登録する必要があります。

<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 制約に加えて)バッテリー残量が少ない場合に処理を実行しないように指定します。

多くの場合、デバイスの充電動作はデバイスをホルダーに置くのと同時に行われます。次のレッスンでは、現在のホルダー状態を判断し、デバイスの装着の変化をモニタリングする方法について説明します。