Search code examples
javaandroidbatterybatterylevel

Get the exact battery level on android


So I currently have the following commonly used method of acquiring the current battery level implemented in my android app.

int getBatteryPercent(){
    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    Intent batteryStatus = this.registerReceiver(null, ifilter);
    int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
    return level;
}

The problem is that this returns an integer 0-100. In order to ensure accuracy of one of my algorithms, I need to be able to get a more precise measure of the battery level. I've seen some battery management apps show the mV which would work perfectly. If anyone knows how to get this value, any help would greatly be appreciated.

To clarify: I need the CURRENT battery level, not the total capacity of the battery.

Thank you!

------------------------UPDATE---------------------------

I am now using the following code:

    // Method for getting the current battery percentage
int getBatteryPercent(){
    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    Intent batteryStatus = this.registerReceiver(null, ifilter);
    int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
    return level;
}

// Method for getting the total battery capacity
double getBatteryCapacity() {
    double battCapacity = 0.0d;
    Object mPowerProfile_ = null;

    Log.d("Debug", "in getBatteryCapacity()");

    final String POWER_PROFILE_CLASS = "com.android.internal.os.PowerProfile";

    try {
        mPowerProfile_ = Class.forName(POWER_PROFILE_CLASS)
                .getConstructor(Context.class).newInstance(this);
    } catch (Exception e) {
        e.printStackTrace();
        Log.d("Debug", "Try 1 - Exception e: " + e.toString());
    }

    try {
        battCapacity = (Double) Class
                .forName(POWER_PROFILE_CLASS)
                .getMethod("getAveragePower", java.lang.String.class)
                .invoke(mPowerProfile_, "battery.capacity");
        Log.d("Debug", "battCapacity is now: " + battCapacity);
    } catch (Exception e) {
        e.printStackTrace();
        Log.d("Debug", "Try 2 - Exception e: " + e.toString());
    }

    Log.d("Debug", "Leaving getBatteryCapacity()");
    return battCapacity;
}

// Method for getting the exact current battery level
double getExactBattery(){
    Log.d("Debug", "In getExactBattery()");
    float batteryPercentage = getBatteryPercent();
    Log.d("Debug", "batteryPercentage = " + batteryPercentage);
    double totalCapacity = getBatteryCapacity();
    Log.d("Debug", "totalCapacity = " + totalCapacity);
    double currLevel = (totalCapacity * (double)batteryPercentage) / 100.0d;
    Log.d("Debug", "currLevel = " + currLevel);
    return currLevel;
}

But the getBatteryCapacity method is giving me a 0.0 return:

01-20 06:37:27.314    7162-7162/com... D/Debug﹕ In getExactBattery()
01-20 06:37:27.324    7162-7162/com... D/Debug﹕ batteryPercentage = 47.0
01-20 06:37:27.329    7162-7162/com... D/Debug﹕ in getBatteryCapacity()
01-20 06:46:00.644    9207-9207/com... D/Debug﹕ battCapacity is now: 0.0
01-20 06:37:27.329    7162-7162/com... D/Debug﹕ Leaving getBatteryCapacity()
01-20 06:37:27.329    7162-7162/com... D/Debug﹕ totalCapacity = 0.0
01-20 06:37:27.329    7162-7162/com... D/Debug﹕ currLevel = 0.0

I have a Droid Ultra running on Android 4.4.4 and this code does not work, it returns 0.0, however when run on an emulator with multiple android versions it does in fact work. I'm curious to see if any other users testing on a Droid Ultra have the same problem. The above code should work on most devices.

This is actually NOT the exact battery level. Using this algorithm if the battery percent was 97% and the total capacity was 1000, the exact battery level would read 970. Now, if the ACTUAL battery percentage is 96.7%, my getBatteryPercent would return 97. This would result in the SAME EXACT ANSWER. So this algorithm is NOT the answer to this question. I am still looking for an answer to this question!!! I need a measure of the battery level that is more precise than +-1%...

------------------------UPDATE---------------------------

I found out that if you use getIntExtra("voltage", -1) in a broadcast receiver listening for ACTION_BATTERY_CHANGED. It gives you the mV. I wonder if this value is reliable enough to use for battery life predictions. Does anyone know of a way I can grab the voltage at any point in time without relying on the most recent update from my broadcast receiver?

EDIT: Turns out it's not viable. this graph shows that battery voltage is a very poor indicator of battery capacity.


Solution

  • Get the battery capacity according @user87049's link and use your own function to get the current battery percentage and combine those two to get a current capacity.

    int batteryPercentage = getBatteryPercentage() //Your function
    double batteryCapacity = getBatteryCapacity() //code from link from user87049. Change it to return value
    double currentCapacity = (batteryPercentage * batteryCapacity) / 100