StickyBroadcast在获取电池状态中的妙用
今天在做开发的时候,突然遇到这样的一个问题,当你的设备电量低于15%的时候这个时候设备的闪光灯是无法打开的,但是我们平台的解决方案对这一块没有做出任何的提示,于是直接导致了用户认为他的闪光灯坏掉了,于是老大要求我们解决这个问题。
我们都知道电池的电量信息获取我们是通过广播来实现的。
标准做法如下:
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { int status = intent.getIntExtra("status", 0); int health = intent.getIntExtra("health", 0); boolean present = intent.getBooleanExtra("present", false); int level = intent.getIntExtra("level", 0); int scale = intent.getIntExtra("scale", 0); int icon_small = intent.getIntExtra("icon-small", 0); int plugged = intent.getIntExtra("plugged", 0); int voltage = intent.getIntExtra("voltage", 0); int temperature = intent.getIntExtra("temperature", 0); String technology = intent.getStringExtra("technology"); 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"; break; case BatteryManager.BATTERY_HEALTH_OVERHEAT: healthString = "overheat"; break; case BatteryManager.BATTERY_HEALTH_DEAD: healthString = "dead"; break; case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE: healthString = "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; } }
获取的具体信息如下:
“status”(int类型)…状态,定义值是BatteryManager.BATTERY_STATUS_XXX。 “health”(int类型)…健康,定义值是BatteryManager.BATTERY_HEALTH_XXX。 “present”(boolean类型) “level”(int类型)…电池剩余容量 “scale”(int类型)…电池最大值。通常为100。 “icon-small”(int类型)…图标ID。 “plugged”(int类型)…充电状态,定义值是BatteryManager.BATTERY_PLUGGED_XXX。 “voltage”(int类型)…mV。 “temperature”(int类型)…温度,0.1度单位。例如 表示197的时候,意思为19.7度。 “technology”(String类型)…电池类型,例如,Li-ion等等。
更详细的我们不深究了,继续回归我们上面的问题
我最开始的想法是通过接受如下广播
<action android:name="android.intent.action.ACTION_BATTERY_LOW"/> <action android:name="android.intent.action.ACTION_BATTERY_OKAY"/>
在SharedPreference 中保持一个状态值来监控,但后来发现根本没有这个必要
这里就要来说一说我们强大的StickyBroadcast
在Google的开发者文档中我们发现
public abstract void sendStickyBroadcast (Intent intent) Since: API Level 1 Perform a sendBroadcast(Intent) that is "sticky," meaning the Intent you are sending stays around after the broadcast is complete, so that others can quickly retrieve that data through the return value of registerReceiver(BroadcastReceiver, IntentFilter). In all other ways, this behaves the same as sendBroadcast(Intent). You must hold the BROADCAST_STICKY permission in order to use this API. If you do not hold that permission, SecurityException will be thrown. Parameters intent The Intent to broadcast;
all receivers matching this Intent will receive the broadcast, and the Intent will be held to be re-broadcast to future receivers.
具体来说是什么意思呢,从字面上来看就是说
这个函数用一种 "sticky"的方式来发送Intent广播,而这样就意味着这个广播在他发出后就会一直滞留(等待),从而让其他所有的注册过本广播的注册者都能够快速的收到本广播。在其他的方式上,他和一般的广播就没有什么差别了。
同时,如果我们希望这样做的话,我们需要
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
这里,我们需要重点关注他关于参数intent的解释:
所有注册了改intent的注册者都将受到该广播。该intent将会保留到该广播被重新发送给它未来的注册者。
可能我解释的不是很清楚,但是有两点我们要说清楚:
一、所有的注册者随时随地都能收到。(随时 的意思是从他发出开始直到他的下次更新为止这段时间内所有注册该广播的都能收到)
二、这条广播会更新,而且一直会维持最新的广播发送给接受者。
好了,解释就到这里,接下来我们来说说他的强大之处
获取当前的电池状态
BatteryManager 会发送“sticky”类型的系统广播,在 Intent 中包括了当前的电池电量状态和充电状态等信息。
因为电池状态的广播类型是 “sticky”类型的,所以我们不需要注册相应的BroadcastReceiver。只需要在调用 registerReceiver 的时候传递空参数null就可以,然后函数的返回值 intent 中就包括了当前电池状态的各种信息。
当然您也可以传递一个自定义的 BroadcastReceiver ,不过实际上也是没有什么必要的。
示例代码:
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); Intent batteryStatus = context.registerReceiver(null, ifilter);
从返回的 Intent 中我们可以获得当前的电池信息,获得方式见上:
例如:
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1); float batteryPct = level / (float)scale;
这样我们就可以获取到电池的电量,从而来判断是否能够开启闪光灯
推荐阅读:
Android
电源管理专题之监测电池电量和充电状态Monitoring the Battery Level and Charging State
http://blog.csdn.net/g_rrrr/article/details/7999026