在Android中获取电池电量和状态

146

我该如何获取电池的电量和状态(插入、放电、充电等)?我查阅了开发人员文档,找到了一个BatteryManager类。但它并不包含任何方法,只有常量。我该如何使用它呢?


经过更多的研究,我找到了BatteryManager.EXTRA_LEVEL。 - Mohit Deshpande
12个回答

154
自从SDK 21 LOLLIPOP,可以使用以下代码来获取当前电池电量百分比:
BatteryManager bm = (BatteryManager) context.getSystemService(BATTERY_SERVICE);
int batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);

阅读Android Developers - BATTERY_PROPERTY_CAPACITY中的BatteryManager。


151

Android教程提供了一个代码示例来说明如何获取电池信息。

简而言之,通过动态设置广播接收器来处理 ACTION_BATTERY_CHANGED 意图,因为它不能通过在清单中声明的组件接收,只能通过使用 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));
  }
}

3
关于Intent.ACTION_BATTERY_CHANGED: 这是一个黏性广播,其中包含有关电池的充电状态、电量和其他信息。您无法通过在清单中声明的组件接收它,只能通过使用Context.registerReceiver()显式注册才能接收到它。 - class Android
2
@class Android 嗯,是的,这在答案中明确说明了。 - SirDarius
1
是的,@SirDarius,只是让其他人知道这件事。我先给你的答案点了赞,当我发现这个问题时才留下了这个评论。 :) - class Android
18
不要忘记在 onPause 或 onDestroy 中取消注册广播接收器。 - Dave Doga Oz
无法使用新的关键字初始化电池管理器,为什么先生? - subhashchandru
显示剩余7条评论

99
根据官方Android文档,您可以在Helper或Util类中使用此方法来获取当前电池百分比:

Java版:
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版本:

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

官方文档中有一个错误,必须使用double而不是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
3
@user2212515,您介意根据官方文档编辑我的答案吗? - blueware
@Ryan,我编辑了我的答案以支持android v21及更高版本,请查看。 - blueware

15

作为 Android 的 BatteryManager 使用粘性 Intent,因此您不必注册实际的 BroadcastReceiver:

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

这是来自https://developer.android.com/training/monitoring-device-state/battery-monitoring.html官方文档。


9

其他答案没有提到如何访问电池状态(充电或未充电)。

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;

3
最终,有人回答了有关电池状态的问题。 - user924

7
您可以使用此功能以百分比获取剩余电量。
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);
    }

6
尝试这个函数,无需权限或任何接收者。
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)));
  }

4
为了检查电池百分比,我们使用 BatteryManager,以下方法将返回电池百分比。

来源链接

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

嘿,我用了这个程序,有时结果是89,有时是00.89,小数点在移动,发生了什么? - Pemba Tamang

3

官方文档有一个错误,你必须使用 double 而不是 float。因为 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);

那个0.53F变成52F的错误是因为将最终值转换为int(从中去除任何小数0.x值),而不是使用Math.round()造成的,对吗? - Robyer

2

在Android-Kotlin中获取电池电量:

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        registerReceiver(this.broadcastReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
    }

    private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
        @SuppressLint("SetTextI18n")
        override fun onReceive(context: Context?, intent: Intent) {
            
            val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
            binding.txtShowBatteryLevel.text = "Battery level: %$level"
            
        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接