Android为了确保应用程序中关键代码的正确执行,提供了WakeLock的API,使得应用程序有权限通过代码阻止AP进入休眠状态。
Wake Lock是一种锁的机制, 只要有人拿着这个锁,系统就无法进入休眠,可以被用户态程序和内核获得. 这个锁可以是有超时的或者是没有超时的,超时的锁会在时间过去以后自动解锁.
如果没有锁了或者超时了, 内核就会启动休眠的那套机制来进入休眠.
WakeLock阻止应用处理器(ApplicationProcessor)挂起,确保关键代码的运行,通过中断唤起应用处理器(ApplicationProcessor),可以阻止屏幕变暗。所有的WakeLock被释放后,系统会挂起
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
WakeLock sCpuWakeLock =pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
|PowerManager.ACQUIRE_CAUSES_WAKEUP,"okTag");
if(sCpuWakeLock !=null) {
sCpuWakeLock.release();
sCpuWakeLock =null;
}
PARTIAL_WAKE_LOCK:保持CPU运转,屏幕和键盘灯有可能是关闭的。
SCREEN_DIM_WAKE_LOCK:保持CPU运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
SCREEN_BRIGHT_WAKE_LOCK:保持CPU运转,保持屏幕高亮显示,允许关闭键盘灯
FULL_WAKE_LOCK:保持CPU运转,保持屏幕高亮显示,键盘灯也保持亮度
ACQUIRE_CAUSES_WAKEUP:不会唤醒设备,强制屏幕马上高亮显示,键盘灯开启。有一个例外,如果有notification弹出的话,会唤醒设备。
ON_AFTER_RELEASE:WakeLock被释放后,维持屏幕亮度一小段时间,减少WakeLock循环时的闪烁情况
如果申请了partialwakelock,那么即使按Power键,系统也不会进Sleep,如Music播放时如果申请了其它的wakelocks,按Power键,系统还是会进Sleep
但如果不领会Android设计者的意图而滥用Wake Lock
API,为了自身程序在后台的正常工作而长时间阻止AP进入休眠状态,就会成为待机电池杀手。
PS:PowerManager.WakeLock 有加锁和解锁两种状态,加锁的方式有两种,一种是永久的锁住,这样的锁除非显式的放开,是不会解锁的,所以这种锁用起来要非常的小心。第二种锁是超时锁,这种锁会在锁住后一段时间解锁。
在创建了 PowerManager.WakeLock 后,有两种机制,第一种是不计数锁机制,另一种是计数锁机制。可以通过 setReferenceCounted(boolean value) 来指定,一般默认为计数机制。这两种机制的区别在于,前者无论 acquire() 了多少次,只要通过一次 release()即可解锁。而后者正真解锁是在( --count == 0 )的时候,同样当 (count == 0) 的时候才会去申请加锁,其他情况 isHeld 状态是不会改变的。所以 PowerManager.WakeLock 的计数机制并不是正真意义上的对每次请求进行申请/释放每一把锁,它只是对同一把锁被申请/释放的次数进行了统计再正真意义上的去操作。一下进行了永久锁的测试: 从测试我们可以看到使用计数和计数锁的区别。
AlarmManager
AlarmManage有一个AlarmManagerService,该服务程序主要维护app注册下来的各类Alarm,并且一直监听Alarm设备,一旦有Alarm触发,或者是Alarm事件发生,AlarmManagerService就会遍历Alarm列表,找到相应的注册Alarm并发出广播
AlarmManager会维持一个cpu的wakelock。这样能保证电话休眠时,也能处理alarm的广播。一旦alarmreceiver的onReceive()方法执行完,wakelock会迅速被释放。如果在receiver中开启一个service,有可能service还没启动,wakelock已经被释放了。所以此时要实现单独的wakelock策略。
有4种Alarm类型:
RTC_WAKEUP
在指定的时刻(设置Alarm的时候),唤醒设备来触发Intent。
RTC
在一个显式的时间触发Intent,但不唤醒设备。
ELAPSED_REALTIME
从设备启动后,如果流逝的时间达到总时间,那么触发Intent,但不唤醒设备。流逝的时间包括设备睡眠的任何时间。注意一点的是,时间流逝的计算点是自从它最后一次启动算起。
ELAPSED_REALTIME_WAKEUP
从设备启动后,达到流逝的总时间后,如果需要将唤醒设备并触发Intent。