当你想通过减少后台更新服务的更新频率来降低程序对电池的影响时,检查电池当前的电量和充电状态将是一个比较好的起点。
程序更新对电池造成的影响将取决于当前电池电量和充电状态,比如说,当设备正在充电的时候,这时的更新对电池的影响是微不足道的,所以这时就是你的程序加大更新力度的最佳时刻。与之相对的是,如果当前设备不是处于充电状态的话,降低程序更新力度对延长续航时间是很必要的。
与之相类似的,如果设备没有处于充电状态,并且是当电池快要用完的时候,这时最好就是将更新力度降到最低甚至是停止更新。
确定电池所处状态
当前电池电量和状态都是通过BatteryManager发送广播,来通知相关的广播接收者的。 个人感觉应该是通过sendStickyBroadcast这种方法发送的广播,这种广播的特点是在广播发送之后,广播的实体Intent会一直存在,意思就是说,在以后调用registerReceiver注册相匹配的Receiver时会把这个Intent对象直接返回给新注册的Receiver,明白这一点对下文是很重要的。
因为BatteryManager广播的是一个sticky的intent实体,这就意味着你不用非得注册一个广播接收者来让你的程序接受这个广播,你可以仅仅就是通过调用registerReceiver这个方法,在需要添加广播接收者位置的参数上传入null,当然你也可以新建一个广播接收者,并在注册广播接收者的时候传入。下面是相关代码:
//设置意图过滤器 IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); //注册广播接收者,因为BatteryManager发送的是sticky形式的intent,所以接收者可以为空 Intent batteryStatus = registerReceiver(null, ifilter); //得到电池当前的状态(共有5种,包括unkonwn、charging、discharging、not charging、full) int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1); //是否处于充电状态 boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ; //充电方式(共有两种,分别是通过AC充电和通过USB端口进行充电) int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB; boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC; //打印相关信息 Log.i("MyBroadcastReceiverActivity","isCharging:"+isCharging+"\nusbCharge:"+usbCharge + "\nacCharge:"+ acCharge);
注意这里是使用的模拟器,其结果如下:
更新程序的最佳时机是:电池状态是使用AC充电状态时,当是使用USB端口进行的充电时,应降低更新频率,当不处于通电状态时,更要降低程序更新频率。
监听电池状态变化
当设备插上电源开始充电时,电池状态便发生了变化,所以对程序员来说,通过监听电池状态的变化来进行相应的更新操作是很重要的。
当设备连上电源或与电源断开连接时,BatteryManager都会发送一个广播。即使这时,你的程序不是出于运行状态,接收这些电池状态变化的信息也是很有必要的,因为你可以控制在后台是否进行相应的更新操作,所以应该为你的程序注册一个广播接收者,来监听接上电源和与电源断开两种状态。这里通过AndroidManifest.xml进行广播接收者的注册,具体如下:
在AndroidManifest.xml中注册一个名为PowerConnectionReceiver的广播接收者:
<receiver android:name=".PowerConnectionReceiver"> <intent-filter> <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/> <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/> </intent-filter> </receiver>
PowerConnectionReceiver 这个类,方法中的内容可参看上文:
public class PowerConnectionReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1); boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL; int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB; boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC; Log.i("PowerConnectionReceiver","isCharing:"+isCharging+"\nusbCharge:"+usbCharge+"\nacCharge:"+acCharge); } }
确定当前电池电量
有时候,确定当前电池的电量也是很有必要的,你可以控制当电池电量低于某值时就降低程序频率或者不再进行程序更新,相关代码如下:
//取得当前电池电量 int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); //取得电池容量 int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1); //计算电池电量使用率 float batteryPct = level / (float)scale; Log.i("MyBroadcastReceiverActivity", "level:"+level+"\nscale:"+scale+"\nbatteryPct:"+batteryPct);
注意,这里仍然是使用的模拟器,结果如下:
监听电池状态的重大变化
一般说来,如果你一直对电池的状态进行监听的话,可能这本身就会对电池造成很大的影响,甚至超过程序本身的影响,这就有点得不偿失了,所以,我们很有必要只监听电池状态的重大变化,比如设备进入了电池电量很低的状态或者从这个状态中出来的时候,下面的代码片段将对这两者情况进行监听,具体如下:
<receiver android:name=".BatteryLevelReceiver"> <intent-filter> <action android:name="android.intent.action.ACTION_BATTERY_LOW"/> <action android:name="android.intent.action.ACTION_BATTERY_OKAY"/> </intent-filter> </receiver>
在广播接收者BatterLevelReceiver类的onReceive方发中,就可以做你想做的了。
下一节,讲介绍怎样确定和监听设备的dock状态和 类型。