一、 监视电量的变化和充电状态
当你通过降低后台任务的更新频率来降低其对电量的影响时,检测当前的电量和充电状态都是一个好的开始好的尝试。
应用的更新对电量的影响最好由剩余电量和充电状态决定。充电时,应用的更新操作对电量的影响可以忽略不计,此时你应该最大化你的刷新频率。相反的没有充电时,降低你应用的更新操作频率来延迟电量使用时间。
相似的你可以检测电量的变化,当电量临近耗尽时,要降低应用更新频率甚至停止应用。
1. 确定当前充电状态:
BatteryManager广播多有的电量和充电信息详情到Intent里。你不需要注册一个BroadcastReceiver,只要简单的调用registerReceiver()并传递一个null作为receiver即可,当前的电量状态信息intent会立刻返回(当然你也可以传递一个BroadcastReceiver对象)。
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = context.registerReceiver(null, ifilter);
你可以检测当前的充电状态,是通过USB方式充电还是插入充电器充电:
// 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;
通常你可以在链接充电器充电时最大化后台更新的频率,链接USB时减低更新频率,没有连接充电时再降低更新频率。
2. 监视充电状态变化
由于充电状态的变化即为容易,根据充电状态的变化决定你应用后台更新的频率变得尤为重要。无论链接或者端口充电设备BatteryManager都会广播一个action,无论你的应用是否运行,能够接受到这个广播都非常重要,尤其是广播会影响你应用的启动来执行后台任务的场景。所有,你需要注册一个BroadcastReceiver到manifest来监听ACTION_POWER_CONNECTED和ACTION_POWER_DISCONNECTED:
<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>
在你的BroadcastReveiver实现里,你可以向前面介绍的方法那样检测电量变化和充电状态变化的信息。
3. 确定当前的剩余电量
确定当前的剩余电量在很多时候也非常有用,在电量耗费到某个水平时你需要降低后台的更新频率。电量的获取也是通过电量信息的intent得到,保护使用电量和电量总容量:
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
float batteryPct = level / (float)scale;
4. 监视电量的变化情况
你不可以一直保持对电量变化的监视,你也不需要这样作!通常来说,持续的保持对电量变化的监控对电量产生的耗费比你的应用的普通内部工作耗费的电还要多。所以监视电量使用的特殊状态是一个好的尝试,尤其是进入或者退出低电量这两个状态。你可以通过注册监听ACTION_BATTERY_LOW和ACTION_BATTERY_OKAY两个状态的receiver来实现。
二、 检测并监控手机的停靠状态和类型
Android设备可以有几种停靠状态,如车在模式、家庭模式等。停靠模式通常直接和充电状态相关,很多停靠模式提供充电和固定设备。停靠模式对你的应用产生什么影响由你自己决定,如可以在桌面停靠时增加更新频率、车载停靠模式时停止刷新,可以在车载停靠模式时最大频率的更新交通流量信息。类似的,停靠状态也是同个Intent广播的,可以通过查询或者注册的方式得到。
查询当前的停靠状态:
IntentFilter ifilter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
Intent dockStatus = context.registerReceiver(null, ifilter);
int dockState = battery.getIntExtra(EXTRA_DOCK_STATE, -1);
boolean isDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
查询当前的停靠类型:
boolean isCar = dockState == EXTRA_DOCK_STATE_CAR;
boolean isDesk = dockState == EXTRA_DOCK_STATE_DESK ||
dockState == EXTRA_DOCK_STATE_LE_DESK ||
dockState == EXTRA_DOCK_STATE_HE_DESK;
监视停靠状态的变化:
<action android:name="android.intent.action.ACTION_DOCK_EVENT"/>
三、 检测并监视手机的联网状态
重复的alarms定时广播和后台的service是非常常见的用法,用来执行定时从internet资源更新应用数据、缓存数据、或者执行长时间的下载任务。但是如果手机没有连接到internet时或者连接的速度非常缓慢导致下载特别慢时,此时不应该保存设备唤醒或者继续执行更新。可以使用ConnectivityManager检测是否连接到internet以及通过什么样的连接方式。
没有联网的时候没有必要在执行基于internet的更新或者下载任务,可以通过如下方式检测:
onnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();
设备的链接状态包括移动网络、ViMAX、Wi-Fi、以太网连接,不同的链接方式提供了不同的带宽和耗电量。可以通过如下方式获取类型:
boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
移动网络耗费明显高于Wi-Fi,大多数时候需要在移动网络时降低更新频率,一些工作甚至要等待Wi-Fi环境才能启动执行。
监视网络变化:ConnectivityManager会在任何连接网络变化的时候广播android.net.connn.CONNECTIVITY_ACTION,可以通过注册监听器receiver监听:
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
四、 控制广播接收的需求
最简单的监听设备状态变化的方式就是注册receiver到manifest来监听响应的状态。通常你会根据设备状态在每个receiver里你会重置定时广播。一个直接的影响就是:每一次广播后你的设备都要被唤醒,潜在的可能超过了本来需要的频率。一个更好的方式是在执行阶段通过代码控制是否启动监听receiver。
可以使用PackageManager来切换manifest里定义的组件的可用不可用状态。例如:
ComponentName receiver = new ComponentName(context, myReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP)
通过这种技术,在手机未联网时,你可以停止所有的receiver除了监听网络变化的receiver。相反的,当你的手机联网后你可以停止对联网的监听,在执行网络操作前简单的检查网络连接性。可以使用同样的技术来延迟需要高带宽的下载任务的执行,监听到连接Wi-Fi的变化后再执行下载任务。