Getting the battery current values for the Android Phone
Asked Answered
U

8

27

I am trying to collect power usage statistics for the Android G1 Phone. I am interested in knowing the values of Voltage and Current, and then able to collect statistics as reported in this PDF.

I am able to get the value of Battery voltage through registering for an intent receiver to receive the Broadcast for ACTION_BATTERY_CHANGED. But the problem is that Android does not expose the value of current through this SDK interface.

One way I tried is via sysfs interface, where I can view the battery current value from adb shell, using the following command

$cat /sys/class/power_supply/battery/batt_current
449 

But that too works only if the phone is connected via USB interface. If I disconnect the phone, I see the value of batt_current as '0'. I am not sure why the value of current reported is zero. It should be more than zero, right?

Any suggestion / pointers for getting battery current value? Also please correct me if I am wrong.

Usquebaugh answered 13/3, 2010 at 19:4 Comment(6)
You might want to watch the presentation for that on YouTube. I was there, and I seem to recall Mr. Sharkey mentioned something about having special hardware for those measurements.Venereal
Here's some sample code that you could try.Protuberant
Thanks for the link, I am using similar function to read the Battery Voltage. But Android doesn't expose the value of current through that interface. So if you know some workaround at kernel / lower layer let me know.Usquebaugh
Yeah, he mentions at the end of the presentation that measuring current is to be done via hardware electronics, software can't help. Do you know how exactly the sysfs interface works and if possible can we takeout data from that. Thanks for pointing me to video.Usquebaugh
hi @Chintan Parikh, have you found a good solution to get current value? There is an App can get current value but I don't know how does it work. play.google.com/store/apps/details?id=com.gombosdev.ampereConvenience
@User9527 Actually, it seems to read data from such files.Anglia
U
3

After several experiments and help from various other groups, I found out that there is no way of getting Battery Current value through software only (as its not supported in h/w). Only way I found was to measure current flowing through battery by means of multimeter.

Usquebaugh answered 11/5, 2010 at 6:47 Comment(3)
Doesnt this do the job? developer.android.com/training/monitoring-device-state/…Stadium
See the answers from @Kevin (and voss) for starters. ;)Circumstantial
Isn't there a current_now?Padraig
K
13

You could just look at the source code for the Current Widget. It has hard coded path's to where certain platforms store the current values.

/*
 *  Copyright (c) 2010-2011 Ran Manor
 *  
 *  This file is part of CurrentWidget.
 *    
 *  CurrentWidget is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  CurrentWidget is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with CurrentWidget.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.manor.currentwidget.library;

import java.io.File;

import android.os.Build;
import android.util.Log;

public class CurrentReaderFactory {

    static public Long getValue() {

        File f = null;      

        // htc desire hd / desire z / inspire?
        if (Build.MODEL.toLowerCase().contains("desire hd") ||
                Build.MODEL.toLowerCase().contains("desire z") ||
                Build.MODEL.toLowerCase().contains("inspire")) {

            f = new File("/sys/class/power_supply/battery/batt_current");
            if (f.exists()) {
                return OneLineReader.getValue(f, false);
            }
        }

        // nexus one cyangoenmod
        f = new File("/sys/devices/platform/ds2784-battery/getcurrent");
        if (f.exists()) {
            return OneLineReader.getValue(f, true);
        }

        // sony ericsson xperia x1
        f = new File("/sys/devices/platform/i2c-adapter/i2c-0/0-0036/power_supply/ds2746-battery/current_now");
        if (f.exists()) {
            return OneLineReader.getValue(f, false);
        }

        // xdandroid
        /*if (Build.MODEL.equalsIgnoreCase("MSM")) {*/
            f = new File("/sys/devices/platform/i2c-adapter/i2c-0/0-0036/power_supply/battery/current_now");
            if (f.exists()) {
                return OneLineReader.getValue(f, false);
            }
        /*}*/

        // droid eris
        f = new File("/sys/class/power_supply/battery/smem_text");      
        if (f.exists()) {
            Long value = SMemTextReader.getValue();
            if (value != null)
                return value;
        }

        // htc sensation / evo 3d
        f = new File("/sys/class/power_supply/battery/batt_attr_text");
        if (f.exists())
        {
            Long value = BattAttrTextReader.getValue();
            if (value != null)
                return value;
        }

        // some htc devices
        f = new File("/sys/class/power_supply/battery/batt_current");
        if (f.exists())
            return OneLineReader.getValue(f, false);

        // nexus one
        f = new File("/sys/class/power_supply/battery/current_now");
        if (f.exists())
            return OneLineReader.getValue(f, true);

        // samsung galaxy vibrant       
        f = new File("/sys/class/power_supply/battery/batt_chg_current");
        if (f.exists())
            return OneLineReader.getValue(f, false);

        // sony ericsson x10
        f = new File("/sys/class/power_supply/battery/charger_current");
        if (f.exists())
            return OneLineReader.getValue(f, false);

        // Nook Color
        f = new File("/sys/class/power_supply/max17042-0/current_now");
        if (f.exists())
            return OneLineReader.getValue(f, false);

        return null;
    }
}
Kartis answered 11/8, 2011 at 18:34 Comment(2)
My GNex running Slimkat has the power level in /sys/class/power_supply/battery/capacity, though it is likely not used here since it is the % value, not current. Interestingly none of your listed files are on my device.Benis
This is GNU license. Is there a nicer license that's used for a similar code? Also, is there a way that covers all devices?Arlenarlena
D
11

API 21 onwards we can get the instantaneous battery current in microamperes, as an integer. Developer docs

BatteryManager mBatteryManager = (BatteryManager) getSystemService(Context.BATTERY_SERVICE);
    Long avgCurrent = null, currentNow = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        avgCurrent = mBatteryManager.getLongProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE);
        currentNow = mBatteryManager.getLongProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_NOW);
    }
    Log.d(TAG, "BATTERY_PROPERTY_CURRENT_AVERAGE = " + avgCurrent + "mAh");
    Log.d(TAG, "BATTERY_PROPERTY_CURRENT_NOW =  " + currentNow + "mAh");

Using mBatteryManager you can get the instantaneous current reading.

Measuring Device Power and reading power consumption and the available properties on NEXUS devices. Android open source docs

Dancy answered 10/8, 2016 at 7:2 Comment(3)
-9223372036854775808 mAh. This is what I get always.Mimetic
This API might give current value but its not always guaranteed to be accurate on all devices as @HiteshDanidhariya mentioned.Extensible
As mentioned in the Android open source docs the device needs to have a fuel gauge hardware for precise reading else it will give arbitrary values in output. Very few devices have this hardware as of today.Dancy
G
5

using this function get Voltage Temperature Current in all devices.

in OnCreate to register broadcast reciever

    this.registerReceiver(this.BatteryInfo, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

and create Broadcast Receiver

    private BroadcastReceiver BatteryInfo = new BroadcastReceiver() {
    @Override
    public void onReceive(Context ctxt, Intent intent) {
        int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
        int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);

        boolean isPresent = intent.getBooleanExtra("present", false);

        Bundle bundle = intent.getExtras();
        String str = bundle.toString();
        Log.i("Battery Info", str);

        if (isPresent) {
            int percent = (level * 100) / scale;

            technology.setText("Technology: "+bundle.getString("technology"));
            voltage.setText("Voltage: "+bundle.getInt("voltage")+"mV");
            temp.setText("Temperature: "+bundle.getInt("temperature"));
            curent.setText("Current: "+bundle.getInt("current_avg"));
            health.setText("Health: "+getHealthString(health_));
            charging.setText("Charging: "+getStatusString(status) + "(" +getPlugTypeString(pluggedType)+")");
            battery_percentage.setText("" + percent + "%");


        } else {
            battery_percentage.setText("Battery not present!!!");
        }
    }   
};


 private String getPlugTypeString(int plugged) {
    String plugType = "Unknown";

    switch (plugged) {
    case BatteryManager.BATTERY_PLUGGED_AC:
        plugType = "AC";
        break;
    case BatteryManager.BATTERY_PLUGGED_USB:
        plugType = "USB";
        break;
    }
    return plugType;
}

private String getHealthString(int health) {
    String healthString = "Unknown";
    switch (health) {
    case BatteryManager.BATTERY_HEALTH_DEAD:
        healthString = "Dead";
        break;
    case BatteryManager.BATTERY_HEALTH_GOOD:
        healthString = "Good Condition";
        break;
    case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
        healthString = "Over Voltage";
        break;
    case BatteryManager.BATTERY_HEALTH_OVERHEAT:
        healthString = "Over Heat";
        break;
    case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
        healthString = "Failure";
        break;
    }
    return healthString;
}
private String getStatusString(int status) {
    String statusString = "Unknown";

    switch (status) {
    case BatteryManager.BATTERY_STATUS_CHARGING:
        statusString = "Charging";
        break;
    case BatteryManager.BATTERY_STATUS_DISCHARGING:
        statusString = "Discharging";
        break;
    case BatteryManager.BATTERY_STATUS_FULL:
        statusString = "Full";
        break;
    case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
        statusString = "Not Charging";
        break;
    }
    return statusString;
}
Greave answered 10/9, 2014 at 10:0 Comment(13)
Is there a way to know if the "current" value is good enough, slow, or even too low to charge (thus the device actually loses power) ? if so, how? Also, will this method work on all devices ? What is the "getHealthString" ,"getStatusString", "getPlugTypeString" methods?Arlenarlena
What is the "getHealthString" ,"getStatusString", "getPlugTypeString" methods? i have edited my answer added methodsGreave
Thank you. can you please answer the other questions too? I've also noticed that for my device, the "current" value is always 0. Why is that?Arlenarlena
check the log output to see battery information, or print str in toast to check if there current_avg exist & whats the valueGreave
As you've already wrote the "str" to the log, I can see that "current_avg" isn't there... :(Arlenarlena
can you tack an screenshot of logcat when show it Battery Info ...Greave
Sure. this is what I see: Bundle[{technology=Li-ion, icon-small=17302984, health=2, status=2, plugged=1, present=true, level=95, scale=100, temperature=350, voltage=4340, invalid_charger=0}]Arlenarlena
Is there maybe a way to get the "current" via other variables that are available here?Arlenarlena
here is my on Galaxy S4. Battery Info: Bundle[{technology=Li-ion, icon-small=17303408, health=2, online=4, status=2, plugged=2, present=true, level=38, scale=100, temperature=306, current_avg=460, voltage=3791, charge_type=1, invalid_charger=0}] [have a look on this] ( https://mcmap.net/q/509943/-getting-the-battery-current-values-for-the-android-phone) it may require root permissionGreave
So it's probably something that OEMs don't have to implement or something. Is it possible to know what is the minimal "current" value that allows the device to still charge itself? or maybe better: is it possible what the device's power usage is, so that I could get a formula whether it's really charging or not, and when it will get fully charged (assuming same value will stay) ? About the link, I don't think it requires root.Arlenarlena
pls use health= intent.getIntExtra("health"); plugStatus= intent.getIntExtra("plugged");Appetizing
in my case isPresent always false even if it is present in fact :)Gavriella
int ht = intent.getExtras().getInt(BatteryManager.EXTRA_HEALTH,-1); int st = intent.getExtras().getInt(BatteryManager.EXTRA_STATUS,-1); int pt = intent.getExtras().getInt(BatteryManager.EXTRA_PLUGGED,-1); String health = getHealthString(ht); String status = getStatusString(st); String plug_type = getPlugTypeString(pt);Garnes
U
3

After several experiments and help from various other groups, I found out that there is no way of getting Battery Current value through software only (as its not supported in h/w). Only way I found was to measure current flowing through battery by means of multimeter.

Usquebaugh answered 11/5, 2010 at 6:47 Comment(3)
Doesnt this do the job? developer.android.com/training/monitoring-device-state/…Stadium
See the answers from @Kevin (and voss) for starters. ;)Circumstantial
Isn't there a current_now?Padraig
S
3

i found this code on Intel android developer site

public class BatteryActivity extends Activity {

    private final String TAG = "SDP_BATTERY";
    private final String DEGREE_UNICODE = "\u00B0";

    private StringBuffer textBuffer = new StringBuffer();

    // a text view to show the status of the battery
    private TextView mStatusTextView;
    // a text view to display the battery status icon
    private TextView mBatteryStatusIcon;

    /** Called when the activity is first created. */
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.battery);

        mBatteryStatusIcon = (TextView) this.findViewById(R.id.statusBattIcon);
        mStatusTextView = (TextView) this.findViewById(R.id.statusEditText);
    }

    /**
     * Once onResume is called, the activity has become visible (it is now "resumed"). Comes after onCreate
     */
    protected void onResume() {
        super.onResume();

        IntentFilter filter = new IntentFilter();

        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        Log.d(TAG, "Register battery status receiver.");
        registerReceiver(mBroadcastReceiver, filter);
    }

    /**
     * Another activity takes focus, so this activity goes to "paused" state
     */
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "Unegister battery status receiver.");
        unregisterReceiver(mBroadcastReceiver);
    }

    /**
     * BroadcastReceiver is used for receiving intents (broadcasted messages) from the BatteryManager
     */
    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {

        private boolean isHealth = false;

        public void onReceive(Context context, Intent intent) {
            DecimalFormat formatter = new DecimalFormat();

            String action = intent.getAction();

            // store battery information received from BatteryManager
            if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                Log.d(TAG, "Received battery status information.");
                int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, 0);
                int health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, 0);
                boolean present = intent.getBooleanExtra(
                        BatteryManager.EXTRA_PRESENT, false);
                int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
                int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
                int icon_small = intent.getIntExtra(
                        BatteryManager.EXTRA_ICON_SMALL, 0);
                int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED,
                        0);
                int voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE,
                        0);
                int temperature = intent.getIntExtra(
                        BatteryManager.EXTRA_TEMPERATURE, 0);
                String technology = intent
                        .getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);

                // display the battery icon that fits the current battery status (charging/discharging)
                mBatteryStatusIcon.setCompoundDrawablesWithIntrinsicBounds(icon_small, 0, 0, 0);

                // create TextView of the remaining information , to display to screen.
                String statusString = "";

                switch (status) {
                case BatteryManager.BATTERY_STATUS_UNKNOWN:
                    statusString = "unknown";
                    break;
                case BatteryManager.BATTERY_STATUS_CHARGING:
                    statusString = "charging";
                    break;
                case BatteryManager.BATTERY_STATUS_DISCHARGING:
                    statusString = "discharging";
                    break;
                case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
                    statusString = "not charging";
                    break;
                case BatteryManager.BATTERY_STATUS_FULL:
                    statusString = "full";
                    break;
                }

                String healthString = "";

                switch (health) {
                case BatteryManager.BATTERY_HEALTH_UNKNOWN:
                    healthString = "unknown";
                    break;
                case BatteryManager.BATTERY_HEALTH_GOOD:
                    healthString = "good";
                    isHealth = true;
                    break;
                case BatteryManager.BATTERY_HEALTH_OVERHEAT:
                    healthString = "overheat";
                    break;
                case BatteryManager.BATTERY_HEALTH_DEAD:
                    healthString = "dead";
                    break;
                case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
                    healthString = "over voltage";
                    break;
                case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
                    healthString = "unspecified failure";
                    break;
                }

                String acString = "";

                switch (plugged) {
                case BatteryManager.BATTERY_PLUGGED_AC:
                    acString = "plugged AC";
                    break;
                case BatteryManager.BATTERY_PLUGGED_USB:
                    acString = "plugged USB";
                    break;
                default:
                    acString = "not plugged";
                }

                textBuffer =  new StringBuffer();
                textBuffer.append("status:" + statusString + "\n");

                formatter.applyPattern("#");
                String levelStr = formatter.format( (float)level/scale * 100 );
                textBuffer.append("level:" + levelStr + "% (out of 100)\n");
                textBuffer.append("health:" + healthString + "\n");

                textBuffer.append("present?:" + String.valueOf(present) + "\n");

                textBuffer.append("plugged?:" + acString + "\n");

                // voltage is reported in millivolts
                formatter.applyPattern(".##");
                String voltageStr = formatter.format( (float)voltage/1000 );
                textBuffer.append("voltage:" + voltageStr + "V\n");

                // temperature is reported in tenths of a degree Centigrade (from BatteryService.java)
                formatter.applyPattern(".#");
                String temperatureStr = formatter.format( (float)temperature/10 );
                textBuffer.append("temperature:" + temperatureStr
                        + "C" + DEGREE_UNICODE + "\n");

                textBuffer.append("technology:" + String.valueOf(technology)
                        + "\n");

                mStatusTextView.setText(textBuffer.toString());

                if (isHealth) {
                    Log.d(TAG, "Battery health: " + healthString);
                    Log.d(TAG, "UMSE_BATTERY_SUCCESSFULLY");
                } else {
                    Log.d(TAG, "UMSE_BATTERY_FAILED");
                }

                Log.d(TAG, textBuffer.toString());

                //finish();
            }
        }
    };
Spada answered 24/12, 2014 at 7:43 Comment(0)
C
1

try this code,may be it would be help full for you:

private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver(){
      @Override
      public void onReceive(Context arg0, Intent intent) {
        // TODO Auto-generated method stub
          //this will give you battery current status
        int level = intent.getIntExtra("level", 0);

        contentTxt.setText(String.valueOf(level) + "%");

        int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
        textView2.setText("status:"+status);
        boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                            status == BatteryManager.BATTERY_STATUS_FULL;
        textView3.setText("is Charging:"+isCharging);
        int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
        textView4.setText("is Charge plug:"+chargePlug);
        boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;

        boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
        textView5.setText("USB Charging:"+usbCharge+" AC charging:"+acCharge);

      }
    };

in main class register this using:

 this.registerReceiver(this.mBatInfoReceiver, 
          new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
Catlike answered 31/5, 2013 at 4:39 Comment(0)
L
0

Most batteries use the current flowing out of the battery to determine the %, though it's rarely available to developpers!

Would require a modified kernel on those devices.

This is true of the Galaxy S2 which have the chips measuring such current flow! But it's "deactivated" in the stock kernel. Meaning it's removed from the sysfs interface and used only internally by the battery.

Nevertheless you can try the app Battery Monitor Widget from Market, it supports many phones and will estimate the mA current when not available. Support for new phones and methods are added on regular basis to improve the readings.

On the Galaxy Nexus, the current chip was completely removed as the battery now uses advanced calculation to determine %, which do not need current data. The results is that that phone doesn't have a learning curve (

Longship answered 6/2, 2012 at 14:0 Comment(0)
A
0

For Battery Current % charge, you could use the following

IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = this.registerReceiver(null, ifilter);

int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);

float batteryPct = level / (float)scale;

TextView tView = (TextView) findViewById(R.id.textView2);
tView.setText("Battery Status " + batteryPct);
Aegisthus answered 4/10, 2015 at 17:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.