1

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.

JayB
  • 397
  • 6
  • 21
  • Probably duplicate of http://stackoverflow.com/questions/23193388/android-get-battery-current-capacity-in-ma-and-total-capacity-of-battery-in-mah – Price Jan 20 '15 at 10:39
  • @user87049 I've read that question/answer already. It's not clearly stated anywhere if the code in the answer is to retrieve the total battery capacity or current battery level. I need the current level – JayB Jan 20 '15 at 10:41
  • What app does this? You could use dex2jar and jd-gui and do a keyword search to see if that helps you understand how they are getting the value. – Jared Rummler Jan 20 '15 at 10:47
  • @JaredRummler Some battery calibration app. I dont remember but I definitely remember seeing an mAH value – JayB Jan 20 '15 at 10:48
  • @JaredRummler Yep. The app is named "Battery Calibration" on the app store. It gives a reading of the current mV – JayB Jan 20 '15 at 10:49

3 Answers3

1

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
0xDEADC0DE
  • 2,453
  • 1
  • 17
  • 22
  • I'm not sure. If you combine this into a single function, why do you want a more simple way? – 0xDEADC0DE Jan 20 '15 at 10:52
  • Doesn't seem to be working. The code from the link is giving me a 0.0 return. I've posted an update to my question with my code – JayB Jan 20 '15 at 11:29
  • Could you debug the `getBatteryCapacity()` function? I think you're entering one of the catch clauses – 0xDEADC0DE Jan 20 '15 at 11:32
  • I understand, but your `battCapacity` is initialized with 0.0 and only set within a `try`. Are you sure you're not entering the catch claus of that try? I the meantime, I also debugged your code and this was my output: `01-20 12:36:16.961 23239-23239/hooff.nl.dummydroid D/Debug﹕ In getExactBattery() 01-20 12:36:36.754 23239-23239/hooff.nl.dummydroid D/Debug﹕ batteryPercentage = 100.0 01-20 12:37:21.368 23239-23239/hooff.nl.dummydroid D/Debug﹕ totalCapacity = 3260.0 01-20 12:38:09.294 23239-23239/hooff.nl.dummydroid D/Debug﹕ currLevel = 3260.0` Tested on Nexus7 2012 with Android 5.0.2 – 0xDEADC0DE Jan 20 '15 at 11:42
  • Too weird. I added a Log.d inside the try, it prints and says that after the assignment, battCapacity is still 0.0. Running a Droid Ultra on 4.4.4. See update for yourself – JayB Jan 20 '15 at 11:48
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/69200/discussion-between-0xdeadc0de-and-jayb). – 0xDEADC0DE Jan 20 '15 at 11:51
  • I found out that if you use getIntExtra("voltage", -1) in a broadcast receiver listening for ACTION_BATTERY_CHANGE. It gives you the mV. I wonder if this is a reliable value to use for battery life predictions. Do you 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? – JayB Jan 20 '15 at 14:05
  • hmm... Can't find it somewhere in the documentation. Maybe you could misuse the behavior of an `IntentFilter`. I think it is triggered once right after it is registered, so if you call `getBatteryPercentage()` again, you would get that value – 0xDEADC0DE Jan 20 '15 at 15:02
  • Nevermind. according to [this graph](http://www.allaboutsymbian.com/reviews/item/15356_PhoNetInfo__.php), voltage does not correspond to battery capacity, so I can't use it. – JayB Jan 20 '15 at 15:07
1

This function will help you.

public float getBatteryPCT()
{
        IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        Intent batteryStatus = this.registerReceiver(null, ifilter);
        int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
        //Check if charging.
        boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;
        //Check if charger plugged in.
        int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
        //check if charging via USB.
        boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
        //check if charging via AC.
        boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
        int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
        float batteryPct = level / (float)scale;
        //Get the current battery percentage.
        return batteryPct*100;
}
Abhishek
  • 2,295
  • 24
  • 28
  • 1
    Doesn't help at all, that returns a value between 0-100, he needs more granular than that. – SMKS Mar 24 '17 at 04:41
-1

According to this answer, you can get the Batter mAH value by the following:

public double getBatteryCapacity() {
    Object mPowerProfile_ = null;

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

    try {
        double batteryCapacity = (Double) Class
                .forName(POWER_PROFILE_CLASS)
                .getMethod("getAveragePower", java.lang.String.class)
                .invoke(mPowerProfile_, "battery.capacity");
        return batteryCapacity;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return 0;
}
Community
  • 1
  • 1
Muhammed Refaat
  • 8,914
  • 14
  • 83
  • 118