Contents
保持设备唤醒... 1
使用wakelock之外的选择... 1
保持屏幕亮... 1
保持CPU运行... 2
用BroadcastReceiver保持设备唤醒... 2
为了避免电量流失,Android设备进入闲置状态后很快就会睡眠。然而,有时应用需要设备保持屏幕或者CPU处于唤醒状态一直到完成某项工作。
应用的需求不同采取的策略也不同。然而一般原则是尽量使用轻量级的方法,最小化应用对系统资源的使用。下面的段落描述了如何处理这种情况,即设备默认的睡眠行为和你的应用的需求不兼容。
在应用使用wakelock前,考虑是否你的需求满足下面几种不建议用wakelock的情况:
一些应用需要保持屏幕亮,比如游戏或视频应用。最好的办法是在Activity里使用FLAG_KEEP_SCREEN_ON(只在Activity,而不在Service或其他应用组件中使用wakelock)。例如:
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
}
这种策略的好处是,不像使用wakelock,他不需要特殊权限,平台可以负责管理用户在应用之间的切换,应用不用关心释放资源的事情。
另一个实现方式是在应用XML布局文件中,用android:keepScreenOn属性:
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true">
...
用android:keepScreenOn=”true”等同于FLAG_KEEP_SCREEN_ON,对你的应用来说,哪个好用就用哪个。在Activity中设置这个属性的好处是,如果不需要了,你可以在后面的程序中选择关掉它,这样屏幕就不会长亮了。
注意:你不需要清除FLAG_KEEP_SCREEN_ON标志,除非你不再需要屏幕保持长亮(例如,你希望在一定时间不活动之后屏幕时间超时)。当应用进入后台运行或者重新进入前台,Window Manager会负责屏幕的亮暗。但是如果你需要显式清除这项标志,以允许屏幕重新关掉,用clearFlags():getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)。
如果你希望设备睡去之前保持CPU运行以完成某项工作,可以用PowerManager的系统服务功能wakelock。Wakelock允许你控制主机的电源状态。
创建和持有wakelock对主机的电池影响巨大。所以只有在非常必要的时候使用wakelock,并且持有时间尽可能短。例如,你永远不需要在Activity中使用wakelock。如上文所述,如果想在Activty中亮,使用FLAG_KEEP_SCREEN_ON。
一个合理的使用wakelock的情况是,后台服务需要获取wakelock,在屏幕关的时候保持CPU运行。再次强调,尽可能减少使用wakelock的时间,因为太耗电了。
要使用wakelock,先在应用manifest文件中加入权限:
android:name="android.permission.WAKE_LOCK" />
如果你的应用包含一个BroadcastReceiver,启动一个服务做一些操作,可以通过WakefulBroadcastReceiver管理你的wakelock。
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::MyWakelockTag"); wakeLock.acquire();
要释放wakelock,调用wakelock.release()。及时释放wakelock很重要。
用BroadcastReceiver和Service管理后台任务的生命周期。
WakefulBroadcastReceiver是一个特殊的BroadcastReceiver,他负责为应用创建和管理PARTIAL_WAKE_LOCK。WakefulBroadcastReceiver把工作传给Service(一般是IntentService),同时保证设备在传输过程中不进入睡眠模式。如果你在传输过程中不保持wakelock,有可能设备进入睡眠模式,而你的任务还没有完成。
使用WakefulBroadcastReceiver的第一步是把它添加到manifest中,就像其他BroadcastReceiver一样。
android:name=".MyWakefulReceiver">
下面的代码用startWakefulService()启动了MyIntentService。相比startService(),这个方法在启动的时候持有一个wakelock。通过startWakefulService()传递的intent中有个extra,指定wakelock类型。
public class MyWakefulReceiver extends WakefulBroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // Start the service, keeping the device awake while the service is // launching. This is the Intent to deliver to the service. Intent service = new Intent(context, MyIntentService.class); startWakefulService(context, service); } }
服务完成时调用MyWakefulReceiver.completeWakefulIntent()释放wakelock。completeWakefulIntent()的参数与从WakefulBroadcastReceiver()传递过来的一样。