Explain Codes LogoExplain Codes Logo

Get battery level and state in Android

java
broadcast-receiver
battery-management
android-development
Anton ShumikhinbyAnton Shumikhin·Sep 18, 2024
TLDR

Retrieve the battery level using Android's BatteryManager:

BatteryManager bm = (BatteryManager) context.getSystemService(Context.BATTERY_SERVICE); int batteryLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); // No magic numbers were harmed in the making of this line.

Check if the device is charging:

IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); Intent batteryStatus = context.registerReceiver(null, ifilter); // No intents were harmed in getting this status. int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1); boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;

How to decode Android's battery gibberish

Using the BatteryManager class to get a hold of battery level and the charging state can be a bit of mental gymnastics. Let’s break it down.

Making Broadcast Receiver your best buddy

You can't register ACTION_BATTERY_CHANGED in the manifest. Use a dynamically registered BroadcastReceiver instead:

BroadcastReceiver batteryLevelReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); float batteryPct = level * 100 / (float)scale; // Elvis has left the building and your battery is charged. } }; IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); context.registerReceiver(batteryLevelReceiver, batteryLevelFilter); // Your battery broadcasts will land here. Fingers crossed for no null pointers.

Remember to unregister the receiver when not needed to save your app from memory leaks.

Charging type: USB or AC, that’s the question

Knowing the charging type—USB or AC—can influence the behavior of your app:

int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB; boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC; // No charges were pressed in identifying the charging type.

Sticky versus dynamic intents: choose your fighter

ACTION_BATTERY_CHANGED is a sticky intent, you can grab it whenever you want. However, if you want real-time updates, go dynamic by registering a receiver in your code.

Tips for making your battery information flow

It’s a jungle out there. Here are some tips for using battery information more efficiently.

Riding the system events wave

Make sure your app adapts to various power states such as power connected/disconnected.

Handling context with grace

Manage context properly when using system services to avoid any unwanted leaks.

Optimise your UI updates

Too frequent UI updates can drain the battery. Remember, with great power (to update) comes great responsibility.

Test, rinse, repeat

Regular testing across different scenarios is crucial for stability and reliability.