监控电池电量和充电状态

本次应用是在锁屏上,显示电量,并且监控充电的状态(设备是否连接电源)

基本思路:

  • 获取当前电量,注册电量变化的广播
  • 监听充电状态,监听设备是否连接电源

#充电状态
在充电的情况下,BatteryManager会通过一个包含充电状态的持续Intent广播所有的电池详情和充电详情.
可以通过注册一个BroadcastReceiver来显示具充电情况.

1
2
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryIntent = context.registerReceiver(null, filter);

如果设备在充电情况下,可以提取当前的充电状态和充电方式.

1
2
3
4
5
6
7
8
9
10
11
12
13
private int getCurrentBattery(final Intent intent) {
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
int battery = (int) (level / (float) scale * 100);
return battery;
}
private boolean isCharging(final Intent intent) {
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
return status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
}

那如何来监控设备是否在充电,也是通过BroadcastReceiver来监听.
只要设备连接或断开电源,BatteryManager就会广播相应的操作.
动态注册:

1
2
3
4
5
6
7
8
9
private void registerPowerReceiver() {
//ACTION_BATTERY_LOW ACTION_BATTERY_OKAY ACTION_POWER_CONNECTED
//ACTION_POWER_DISCONNECTED
batteryRecevier = new BatteryRecevier();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_POWER_CONNECTED);
filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
registerReceiver(batteryRecevier, filter);
}

在配置文件中声明:

1
2
3
4
5
6
<receiver android:name=".BatteryRecevier">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
</intent-filter>
</receiver>

#电量变化
获取电量变化,上面也有提到,只要注册了 Intent.ACTION_BATTERY_CHANGEDBroadcastReceiver,可以通过下面代码获取到电量情况:

1
2
3
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
int battery = (int) (level / (float) scale * 100);

#API相关
上面介绍了获取电量和充电的状态,使用了其他中一些BatteryManager api.
如果要比较完整的使用,可以参考以下api

##Extra声明

EXTRA 说明
EXTRA_HEALTH 电池健康情况
EXTRA_ICON_SMALL 电量状况的图标
EXTRA_LEVEL 电池电量
EXTRA_PLUGGED 充电类型
EXTRA_PRESENT 是否有电池
EXTRA_SCALE 电池最大容量
EXTRA_STATUS 电池状态
EXTRA_TECHNOLOGY 电池制造技术(Li)
EXTRA_TEMPERATURE 电池温度
EXTRA_VOLTAGE 电池伏数

上述的都是ACTION_BATTERY_CHANGED提供的.

##常量声明

###EXTRA_HEALTH
常量 | 含义 |
—-|——|
BATTERY_HEALTH_COLD | 电池冷却 |
BATTERY_HEALTH_DEAD | 电池没电 |
BATTERY_HEALTH_GOOD | 电池良好 |
BATTERY_HEALTH_OVERHEAT | 电池过热 |
BATTERY_HEALTH_OVER_VOLTAGE | 过电压 |
BATTERY_HEALTH_UNKNOWN | 未知原因 |
BATTERY_HEALTH_UNSPECIFIED_FAILURE | 未定义错误 |

###EXTRA_PLUGGED
常量 | 含义 |
—-|——|
BATTERY_PLUGGED_AC | AC充电器 |
BATTERY_PLUGGED_USB | USB充电 |
BATTERY_PLUGGED_WIRELESS | 无线充电 |

###EXTRA_STATUS
常量 | 含义 |
—-|——|
BATTERY_STATUS_CHARGING | 正在充电 |
BATTERY_STATUS_DISCHARGING | 放电中 |
BATTERY_STATUS_FULL | 电池满 |
BATTERY_STATUS_NOT_CHARGING | 未充电 |
BATTERY_STATUS_UNKNOWN | 未知状态 |

#应用实例
该应用实例只是演示了监控电池电量和充电状态.
Battery Samples

#深入了解
电池及充电相关的服务BatteryService,实现了电池电量和充电的状态.

##监听UEvent,读取invalid_charger/state里中的状态
实现了一个UEvent的观察者。uevent是Linux内核用来向用户空间主动上报事件的机制,对于JAVA程序来说,只实现UEventObserver的虚函数onUEvent,然后注册即可.
android4.4后,实现电量和充电状态的代码:

1
2
3
4
5
6
7
8
9
10
11
12
private final UEventObserver mInvalidChargerObserver = new UEventObserver() {
@Override
public void onUEvent(UEventObserver.UEvent event) {
final int invalidCharger =
"1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
synchronized (mLock) {
if (mInvalidCharger != invalidCharger) {
mInvalidCharger = invalidCharger;
}
}
}
};

在初始化BatteryService中:

1
2
3
4
5
6
7
8
9
public BatteryService(Context context) {
....
// watch for invalid charger messages if the invalid_charger switch exists
if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
mInvalidChargerObserver.startObserving(
"DEVPATH=/devices/virtual/switch/invalid_charger");
}
}

声明的Listener,监听电量和充电情况:

1
2
3
4
5
6
7
8
9
10
11
private final class BatteryListener extends IBatteryPropertiesListener.Stub {
@Override
public void batteryPropertiesChanged(BatteryProperties props) {
final long identity = Binder.clearCallingIdentity();
try {
BatteryService.this.update(props);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}

update之后通过processValuesLocked方法更新,并广播一个Intent来通知其它关注电源状态的组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
private void sendIntentLocked() {
// Pack up the values and broadcast them to everyone
final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_REPLACE_PENDING);
int icon = getIconLocked(mBatteryProps.batteryLevel);
intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus);
intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth);
intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryProps.batteryPresent);
intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryProps.batteryLevel);
intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);
intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);
intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryProps.batteryVoltage);
intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryProps.batteryTemperature);
intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryProps.batteryTechnology);
intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
if (DEBUG) {
Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel +
", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus +
", health:" + mBatteryProps.batteryHealth + ", present:" + mBatteryProps.batteryPresent +
", voltage: " + mBatteryProps.batteryVoltage +
", temperature: " + mBatteryProps.batteryTemperature +
", technology: " + mBatteryProps.batteryTechnology +
", AC powered:" + mBatteryProps.chargerAcOnline + ", USB powered:" + mBatteryProps.chargerUsbOnline +
", Wireless powered:" + mBatteryProps.chargerWirelessOnline +
", icon:" + icon + ", invalid charger:" + mInvalidCharger);
}
mHandler.post(new Runnable() {
@Override
public void run() {
ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
}
});
}

接收ACTION_BATTERY_CHANGED广播,就可以监听电量和充电状态.
android 2.3中的实现:
参考文章:http://blog.csdn.net/absurd/article/details/4814858

yeungeek wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
曾经有一份打赏放在我面前,我没有珍惜.如果上天给我再来一次的机会,我会说三个字:赏死我.