Comprehensive Technical Guide to Monitoring Battery Level and State in Android

Dec 03, 2025 · Programming · 15 views · 7.8

Keywords: Android | Battery Level | Battery State | Broadcast Receiver | BatteryManager | Java | Kotlin | Version Compatibility

Abstract: This article explores multiple methods for retrieving battery level and state in Android applications, including using broadcast receivers to dynamically listen for ACTION_BATTERY_CHANGED intents and leveraging modern APIs from the BatteryManager class. Based on best practices, it provides Java and Kotlin code examples and addresses compatibility issues across different Android versions, aiming to help developers efficiently manage device power states.

Introduction

In Android development, monitoring device battery level and state is crucial for optimizing user experience and energy efficiency. Developers often need to access battery information, such as percentage charge and charging status (e.g., charging, discharging, or plugged in), to adjust application behavior or provide relevant notifications. However, the Android system offers various approaches to achieve this, primarily involving the BatteryManager class and broadcast receivers.

Using Broadcast Receivers to Get Battery Information

A traditional and widely used method involves dynamically registering a broadcast receiver to listen for the system-broadcast ACTION_BATTERY_CHANGED intent. Since this intent cannot be received via components declared in manifests, it must be explicitly registered at runtime using Context.registerReceiver(). The following is a basic implementation example demonstrating how to set up a broadcast receiver in an Activity and calculate battery percentage.

public class MainActivity extends Activity {
    private TextView batteryTextView;
    private BroadcastReceiver batteryReceiver = 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);
            if (level != -1 && scale != -1) {
                float batteryPercentage = level * 100 / (float) scale;
                batteryTextView.setText(String.valueOf(batteryPercentage) + "%");
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        batteryTextView = findViewById(R.id.batteryTxt);
        IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(batteryReceiver, filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(batteryReceiver);
    }
}

This method directly handles extras from the intent, such as EXTRA_LEVEL and EXTRA_SCALE, to compute battery percentage without relying on specific Android versions.

Using Modern Methods with BatteryManager

Starting from Android 5.0 (LOLLIPOP, SDK 21), the BatteryManager class introduced more convenient APIs that allow developers to directly retrieve battery properties. For example, the getIntProperty() method can be used to easily obtain battery capacity as a percentage. The following code snippet illustrates how to use this method in Android 5.0 and above.

public static int getBatteryPercentage(Context context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        BatteryManager batteryManager = (BatteryManager) context.getSystemService(Context.BATTERY_SERVICE);
        return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
    } else {
        return -1; // Handle older versions
    }
}

This approach simplifies code by avoiding the complexity of dynamic broadcast receivers but is limited to newer system versions.

Handling Version Compatibility

To ensure application compatibility across a wide range of Android devices, developers need to combine the above methods. A comprehensive solution includes conditional logic to select the optimal method based on the device's system version. Below is an example of a Helper class providing Java and Kotlin implementations to retrieve battery percentage while supporting all Android versions.

// Java version
public class BatteryUtils {
    public static int getBatteryPercentage(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            BatteryManager bm = (BatteryManager) context.getSystemService(Context.BATTERY_SERVICE);
            return bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
        } else {
            IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
            Intent batteryStatus = context.registerReceiver(null, filter);
            if (batteryStatus != null) {
                int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
                int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
                if (level != -1 && scale != -1) {
                    double batteryPct = level / (double) scale;
                    return (int) (batteryPct * 100);
                }
            }
            return -1; // Indicates failure to retrieve
        }
    }
}

// Kotlin version
fun getBatteryPercentage(context: Context): Int {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        val bm = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
        bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
    } else {
        val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
        val batteryStatus: Intent? = context.registerReceiver(null, filter)
        val level = batteryStatus?.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) ?: -1
        val scale = batteryStatus?.getIntExtra(BatteryManager.EXTRA_SCALE, -1) ?: -1
        if (level != -1 && scale != -1) {
            val batteryPct = level / scale.toDouble()
            (batteryPct * 100).toInt()
        } else {
            -1
        }
    }
}

This implementation prioritizes modern APIs for efficiency while falling back to the broadcast receiver method for older versions.

Conclusion

Retrieving battery level and state in Android devices is a common requirement in development. By combining broadcast receivers with BatteryManager APIs, developers can build robust and compatible solutions. It is recommended to adopt conditional logic in applications to handle different Android versions, ensuring optimal performance and user experience. Future updates to Android may introduce additional APIs, but current methods cover mainstream devices from older to newer versions.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.