android计时与系统休眠

android计时与系统休眠摘要:之前做项目的时候,修改一个倒计时秒表,本来以为比较简单,但是发现很多有趣的东西。我们项目里面用的是Timer计时的方法,但是,当系统休眠的时候,Timer也是处于休眠状态的。后来,我改进了几个方法,一个是handle+message的方法,,还有一个是handle+runnable的方法,还有handle+Thread的方法。但是同样发现系统休眠的时候,这些同样是处于休眠状态的。后来上网查找了一下,这和android的架构有关: 原理 Android手机有两个处理器,一个叫Application Processor(AP),一个叫Baseband Processor(BP)。AP是ARM架构的处理器,用于运行Linux+Android系统;BP用于运行实时操作系统(RTOS),通讯协议栈运行于BP的RTOS之上。非通话时间,BP的能耗基本上在5mA左右,而AP只要处于非休眠状态,能耗至少在50mA以上,执行图形运算时会更高。另外LCD工作时功耗在100mA左右,WIFI也在100mA左右。一般手机待机时,AP、LCD、WIFI均进入休眠状态,这时Android中应用程序的代码也会停止执行。Android为了确保应用程序中关键代码的正确执行,提供了Wake Lock的API,AlarmManager这个类使用的是BP的芯片,使得应用程序有权限通过代码阻止AP进入休眠状态。但如果不领会Android设计者的意图而滥用Wake Lock API,为了自身程序在后台的正常工作而长时间阻止AP进入休眠状态,就会成为待机电池杀手。

首先,完全没必要担心AP休眠会导致收不到消息推送。通讯协议栈运行于BP,一旦收到数据包,BP会将AP唤醒,唤醒的时间足够AP执行代码完成对收到的数据包的处理过程。其它的如Connectivity事件触发时AP同样会被唤醒。那么唯一的问题就是程序如何执行向服务器发送心跳包的逻辑。你显然不能靠AP来做心跳计时。Android提供的Alarm Manager就是来解决这个问题的。Alarm应该是BP计时(或其它某个带石英钟的芯片,不太确定,但绝对不是AP),触发时唤醒AP执行程序代码。那么Wake Lock API有啥用呢?比如心跳包从请求到应答,比如断线重连重新登陆这些关键逻辑的执行过程,就需要Wake Lock来保护。而一旦一个关键逻辑执行成功,就应该立即释放掉Wake Lock了。两次心跳请求间隔5到10分钟,基本不会怎么耗电。除非网络不稳定,频繁断线重连,那种情况办法不多。

网上有说使用AlarmManager,因为AlarmManager 是Android 系统封装的用于管理 RTC 的模块,RTC (Real Time Clock) 是一个独立的硬件时钟,可以在 CPU 休眠时正常运行,在预设的时间到达时,通过中断唤醒 CPU。

实验

后来,本人使用AlarmManager,但是又碰到不准的问题,而且当系统繁忙的时候(比如刚开机前一分钟),更为明显,后来查看官方的API说明。因为我之前使用的方法大致是下面的原理:

[java]view plain

然后注册一个广播接收器接收

需要的操作;}

我们看看官方给出的API说明:Note:as of API 19, all repeating alarms are inexact. If your application needs precise delivery times then it must use one-time exact alarms, rescheduling each time as described above. Legacy applications whosetargetSdkVersionis earlier than API 19 will continue to have all of their alarms, including repeating alarms, treated as exact.意思大概是说19或者19以后,为了优化电池,该计时操作不准确了(可能在定义时间之后响应),但是19之前的任然准确。

If your application has strong ordering requirements there are other APIs that you can use to get the necessary behavior; seesetWindow(int, long, long, PendingIntent)andsetExact(int, long, PendingIntent).意思是虽然19(包括)之后可能不准确,但是android保留了两个接口,这两个接口是准确的。本人于是使用了这其中一个。

方法如下 TIP:前提是确保你的API是19的或更高,否则做下判断

public static boolean isKitKatOrLater() {

return Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2;

}

[java]view plain

[java]view plain

if(isKitKatOrLater(){am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime()+1000,sendIntent);}

然后注册一个广播接收器接收

[java]view plain

if(isKitKatOrLater(){}

[java]view plain

if(isKitKatOrLater(){am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime()+1000,sendIntent); 需要的操作;}

但是后来有发现,即使使用了精确的时间计时,但是在系统刚开机的一分钟内计时,仍然会有不及时响应的情况,所以,后来自己想了一下,毕竟是两块芯片,多进程多线程还要考虑好多同步的问题,两块芯片也不可能配合的那么天衣无缝,假如一块特别繁忙的时候。所以,后来我参考源码的方法:正常情况下使用线程或者Timer计时,并且使用AlarmManager设定一个计时结束的时间,当执行Activity的Onpause的时候使用AlarmManager的计时响应。当Onresume的时候,根据走过的时间刷新界面。

或许是某座闻名遐迩的文化古城。我们可以沿途用镜头记录彼此的笑脸,

android计时与系统休眠

相关文章:

你感兴趣的文章:

标签云: