113

How can I get battery level and state (plugged in, discharging, charging, etc)? I researched the developer docs and I found a BatteryManager class. But it doesn't contain any methods, just constants. How do I even use it?

Mohit Deshpande
  • 48,747
  • 74
  • 187
  • 247

10 Answers10

133

Here is a code sample that explains how to get battery information.

To sum it up, a broadcast receiver for the ACTION_BATTERY_CHANGED intent is set up dynamically, because it can not be received through components declared in manifests, only by explicitly registering for it with Context.registerReceiver().

public class Main extends Activity {
  private TextView batteryTxt;
  private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver(){
    @Override
    public void onReceive(Context ctxt, Intent intent) {
      int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
      int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
      float batteryPct = level * 100 / (float)scale;
      batteryTxt.setText(String.valueOf(batteryPct) + "%");
    }
  };

  @Override
  public void onCreate(Bundle b) {
    super.onCreate(b);
    setContentView(R.layout.main);
    batteryTxt = (TextView) this.findViewById(R.id.batteryTxt);
    this.registerReceiver(this.mBatInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
  }
}
SirDarius
  • 36,426
  • 7
  • 79
  • 95
  • 2
    About Intent.ACTION_BATTERY_CHANGED: This is a sticky broadcast containing the charging state, level, and other information about the battery. You can not receive this through components declared in manifests, only by explicitly registering for it with Context.registerReceiver(). – class Android May 06 '15 at 11:44
  • 2
    @classAndroid well, yes, that's explicitely stated in the answer. – SirDarius May 06 '15 at 12:06
  • Yes @SirDarius, just letting others know about it. I upvoted your answer first and put this comment when I found it out. :) – class Android May 06 '15 at 12:52
  • 15
    don't forget to unRegisterReceiver onPause or onDestroy. – Dave Doga Oz Jul 05 '15 at 19:02
  • Cannot able to instaialise battery manager with new Keywork , Why sir ? – subhashchandru Dec 19 '19 at 04:27
  • EXTRA_LEVEL is not exact. You need to scale it. See [this link](https://developer.android.com/training/monitoring-device-state/battery-monitoring#CurrentLevel) for detail. – Robin Hsu Feb 19 '21 at 11:21
  • there is no state, only level, why it was accept if it's not a full answer? – user924 Apr 08 '21 at 12:24
  • @user924 if you think you can improve this answer, please feel free to do so. If the Original Poster accepted this answer, I believe they were satisfied with the contents. – SirDarius Apr 08 '21 at 13:09
  • from author question __Get battery level and **state** in Android__. Is there any code to get state in your code? no :) Check here https://stackoverflow.com/a/59025376/7767664 – user924 Apr 08 '21 at 20:26
119

Since SDK 21 LOLLIPOP it is possible to use the following to get current battery level as a percentage:

BatteryManager bm = (BatteryManager) context.getSystemService(BATTERY_SERVICE);
int batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);

Read BatteryManager  |  Android Developers - BATTERY_PROPERTY_CAPACITY

Roshana Pitigala
  • 7,058
  • 8
  • 38
  • 66
Mark
  • 2,796
  • 1
  • 19
  • 25
77

Based on official android docs, you can use this method in a Helper or Util class to get current battery percentage:

Java version:

public static int getBatteryPercentage(Context context) {

    if (Build.VERSION.SDK_INT >= 21) {

         BatteryManager bm = (BatteryManager) context.getSystemService(BATTERY_SERVICE);
         return bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);

    } else {

         IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
         Intent batteryStatus = context.registerReceiver(null, iFilter);

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

         double batteryPct = level / (double) scale;

         return (int) (batteryPct * 100);
   }
}

Kotlin version:

fun getBatteryPercentage(context: Context): Int {
    return if (Build.VERSION.SDK_INT >= 21) {
        val bm = context.getSystemService(BATTERY_SERVICE) as BatteryManager
        bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
    
    } else {
        val iFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
        val batteryStatus: Intent = context.registerReceiver(null, iFilter)
        val level = batteryStatus?.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
        val scale = batteryStatus?.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
        val batteryPct = level / scale.toDouble()
        (batteryPct * 100).toInt()
    }
}
blueware
  • 4,309
  • 1
  • 32
  • 59
  • one mistake in official docs, you must use double instead float int level = batteryStatus != null ? batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) : -1; int scale = batteryStatus != null ? batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1) : -1; double batteryPct = (double) level / (double) scale; int percent = (int) (batteryPct * 100D); – user2212515 Aug 04 '18 at 13:41
  • 2
    @user2212515, would you mind edit my answer based on the official docs? – blueware Aug 04 '18 at 17:49
  • @Ryan, I edited my answer to support android v21 and later. Please check it out. – blueware Nov 19 '19 at 09:32
  • no state, only level – user924 Apr 08 '21 at 12:25
14

You don't have to register an actual BroadcastReceiver as Android's BatteryManager is using a sticky Intent:

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

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

float batteryPct = level / (float)scale;

return (int)(batteryPct*100);

This is from the official docs over at https://developer.android.com/training/monitoring-device-state/battery-monitoring.html.

bk138
  • 2,749
  • 1
  • 29
  • 23
7

You can use this to get remaining charged in percentage.

private void batteryLevel() {
        BroadcastReceiver batteryLevelReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                context.unregisterReceiver(this);
                int rawlevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
                int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
                int level = -1;
                if (rawlevel >= 0 && scale > 0) {
                    level = (rawlevel * 100) / scale;
                }
                batterLevel.setText("Battery Level Remaining: " + level + "%");
            }
        };
        IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(batteryLevelReceiver, batteryLevelFilter);
    }
reza.cse08
  • 5,172
  • 38
  • 34
5

try this function no need permisson or any reciver

void getBattery_percentage()
{
      IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
      Intent batteryStatus = getApplicationContext().registerReceiver(null, ifilter);
      int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
      int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
      float batteryPct = level / (float)scale;
      float p = batteryPct * 100;

      Log.d("Battery percentage",String.valueOf(Math.round(p)));
  }
milan pithadia
  • 552
  • 5
  • 12
4

To check battery percentage we use BatteryManager, the following method will return battery percentage.

Source Link

public static float getBatteryLevel(Context context, Intent intent) {
    Intent batteryStatus = context.registerReceiver(null,
            new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    int batteryLevel = -1;
    int batteryScale = 1;
    if (batteryStatus != null) {
        batteryLevel = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, batteryLevel);
        batteryScale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, batteryScale);
    }
    return batteryLevel / (float) batteryScale * 100;
}
Code Spy
  • 7,520
  • 3
  • 57
  • 39
4

Other answers didn't mention how to access battery status (chraging or not).

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

// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                     status == BatteryManager.BATTERY_STATUS_FULL;

// How are we charging?
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
FindOutIslamNow
  • 838
  • 1
  • 10
  • 25
1
private void batteryLevel() {
        BroadcastReceiver batteryLevelReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                context.unregisterReceiver(this);
                int rawlevel = intent.getIntExtra("level", -1);
                int scale = intent.getIntExtra("scale", -1);
                int level = -1;
                if (rawlevel >= 0 && scale > 0) {
                    level = (rawlevel * 100) / scale;
                }
                mBtn.setText("Battery Level Remaining: " + level + "%");
            }
        };
        IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(batteryLevelReceiver, batteryLevelFilter);
    }
Hardip
  • 320
  • 2
  • 9
1

one mistake in official docs, you must use double instead float. Because 0.53F * 100F = 52F

int level = batteryStatus != null ? 
batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) : -1; int scale = 
batteryStatus != null ? batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1) : -1; 
double batteryPct = (double) level / (double) scale; int percent = (int) (batteryPct * 100D);
user2212515
  • 1,150
  • 1
  • 11
  • 9
  • Isn't that 0.53F -> 52F mistake caused by casting final value to int (thus stripping any decimal 0.x value from it), instead of using Math.round()? – Robyer Oct 26 '18 at 16:48