Giám sát mức pin và trạng thái sạc

Khi bạn thay đổi tần suất cập nhật ở chế độ nền để giảm tác động của các bản cập nhật đó lên thời lượng pin, bạn nên bắt đầu bằng cách kiểm tra mức pin hiện tại và trạng thái sạc.

Mức tác động của việc cập nhật ứng dụng đến thời lượng pin phụ thuộc vào mức pin và trạng thái sạc của thiết bị. Tác động của việc cập nhật trong khi thiết bị đang sạc qua AC là không đáng kể, vì vậy, trong hầu hết các trường hợp, bạn có thể tối đa hoá tốc độ làm mới bất cứ khi nào thiết bị được kết nối với bộ sạc cắm tường. Ngược lại, nếu thiết bị đang sạc, việc giảm tốc độ cập nhật sẽ giúp kéo dài thời lượng pin.

Tương tự, bạn có thể kiểm tra mức pin, có thể giảm tần suất (hoặc thậm chí dừng) các bản cập nhật khi pin sắp hết.

Xác định trạng thái sạc hiện tại

Hãy bắt đầu bằng cách xác định trạng thái sạc hiện tại. BatteryManager sẽ truyền tất cả thông tin chi tiết về pin và trạng thái sạc trong một Intent cố định, bao gồm cả trạng thái sạc.

Vì đây là một ý định cố định, nên bạn không cần đăng ký BroadcastReceiver – chỉ cần gọi registerReceiver truyền vào null làm trình thu nhận như minh hoạ trong đoạn mã tiếp theo, ý định về trạng thái pin hiện tại sẽ được trả về. Bạn có thể truyền một đối tượng BroadcastReceiver thực tế tại đây, nhưng chúng ta sẽ xử lý thông tin cập nhật trong phần sau nên việc này là không cần thiết.

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

Bạn có thể trích xuất cả trạng thái sạc hiện tại và nếu thiết bị đang được sạc, cho dù thiết bị đang sạc qua USB hay bộ sạc 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;

Thông thường, bạn nên tăng tốc độ cập nhật ở chế độ nền trong trường hợp thiết bị được kết nối với bộ sạc AC, giảm tốc độ nếu sạc qua USB và giảm tốc độ hơn nữa nếu pin đang xả.

Theo dõi các thay đổi về trạng thái sạc

Trạng thái sạc có thể thay đổi dễ dàng như khi cắm thiết bị vào nguồn điện. Vì vậy, bạn cần phải theo dõi trạng thái sạc để biết các thay đổi và thay đổi tốc độ làm mới cho phù hợp.

BatteryManager sẽ truyền một hành động bất cứ khi nào thiết bị được kết nối hoặc ngắt kết nối với nguồn điện. Bạn cần phải nhận được những sự kiện này ngay cả khi ứng dụng không chạy (đặc biệt là khi các sự kiện này sẽ ảnh hưởng đến tần suất bạn khởi động ứng dụng để bắt đầu quá trình cập nhật ở chế độ nền). Vì vậy, bạn nên đăng ký BroadcastReceiver trong tệp kê khai để theo dõi cả hai sự kiện bằng cách xác định ACTION_POWER_CONNECTEDACTION_POWER_DISCONNECTED trong bộ lọc ý định.

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

Xác định mức pin hiện tại

Trong một số trường hợp, việc xác định mức pin hiện tại cũng rất hữu ích. Bạn có thể chọn giảm tốc độ cập nhật ở chế độ nền nếu pin sạc dưới một mức nhất định.

Bạn có thể tìm thấy mức pin hiện tại bằng cách trích xuất mức pin hiện tại và quy mô từ ý định trạng thái pin như minh hoạ dưới đây:

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;

Phản ứng với những thay đổi đáng kể về mức pin

Bạn không thể dễ dàng theo dõi liên tục trạng thái pin, nhưng việc này là không cần thiết.

Nói chung, tác động của việc theo dõi mức pin có tác động lớn hơn đến pin so với hành vi thông thường của ứng dụng. Ví dụ: việc đăng ký BroadcastReceiver trong tệp kê khai để huỷ công việc đang chờ xử lý khi pin yếu sẽ chủ yếu làm tiêu hao pin hơn nữa (và do đó không thể thực hiện được kể từ Android 8.0). Thay vào đó, bạn có thể cung cấp các quy tắc ràng buộc về công việc mô tả thời điểm chạy công việc đó, cho phép hệ thống đưa ra quyết định mà không cần tiêu tốn năng lượng để khởi động ứng dụng.

Nhìn chung, bạn không nên chạy bản cập nhật ở chế độ nền khi pin yếu. Dữ liệu của bạn mới đến đâu cũng không quan trọng nếu điện thoại tự tắt trước khi bạn có thể sử dụng dữ liệu đó. Để thực hiện việc này, hãy sử dụng thư viện WorkManager với quy tắc ràng buộc BatteryNotLow để chỉ định rằng không nên chạy công việc nếu pin yếu (bên cạnh mọi quy tắc ràng buộc NetworkType có liên quan).

Trong nhiều trường hợp, việc sạc thiết bị trùng với việc đặt thiết bị vào đế sạc. Để tìm hiểu thêm, hãy xem phần Xác định và theo dõi trạng thái cũng như loại đế sạc.