功耗问题研究——定时唤醒机制实际效果

来源:互联网 发布:熊猫 知乎 编辑:程序博客网 时间:2024/05/16 17:56

实验设备android版本:7.0

android开发的小伙伴们使用频度最高的Handler和Message,在系统进入深度休眠之后,是无法正确执行的,因此有些时候小伙伴们可能会疑惑为什么我明明由Handler发出了一个定时任务(Message或Runnable),但为什么没有执行呢?

但是过度的担心休眠问题,而全程持有wacklock,也是没有必要的。因为实际情况下,系统有很多机会被唤醒,比如来电、短信、网络状态变更、网络侧过来了数据包等等,只不过需要注意的是,这样的唤醒有可能是短暂的(系统可能很快再次睡下去),如果你有耗时的操作,那么你需要在这样的唤醒节点申请wacklock,并在耗时操作执行完毕后,释放掉wacklock,这样才能确保代码的正确执行。

对于需要与后台保持长连接心跳或者其他定时周期性主动交互的程序,那么可能需要用到系统的定时唤醒机制。通常安卓系统定时唤醒机制的参考打开方式,分以下三步:

1、自定义广播

Intent intent_alarm = new Intent("com.tgt.device.manager.RTC_WAKEUP");

2、定义该广播的接收器(由于这里采用了指定发送的方式,因此该receiver并不需要声明IntentFilter)

public class WackupBroadcastReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        String action = intent.getAction();        if("com.tgt.device.manager.RTC_WAKEUP".equals(action)){//唤醒设备            //你的代码,如果有耗时操作,请申请wacklock,并在操作结束后释放。        }    } }

3、通过AlarmManager的api设置配置参数并定时发送该广播

public static void setWakeupRepeatTask(){    Intent intent_alarm = new Intent("com.tgt.device.manager.RTC_WAKEUP");    intent_alarm.setClassName(App.getContext(), WackupBroadcastReceiver.class.getName());    if (pi==null){        pi = PendingIntent.getBroadcast(App.getContext(),0,intent_alarm,0);    }    if (am==null){        am = (AlarmManager)App.getContext().getSystemService(ALARM_SERVICE);    }    if (am !=null && pi!=null){        am.cancel(pi);        int first = 300;        logd("设置唤醒闹钟,第一次唤醒在" + first + "s后,后续唤醒间隔:" + heartBeatInterval + "s");        //有效,第一次发起的时间不固定,后续间隔固定        am.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (first * 1000), heartBeatInterval * 1000, pi);        //有效,第一次发起的时间设置为5分钟是准确的,设置1分钟不准确,后续间隔也固定        //am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+(first*1000),heartBeatInterval*1000,pi);        //无效,有时候能唤醒,有时候无法唤醒        //am.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+heartBeatInterval*1000, pi);        }    }

关于配置参数AlarmManager.RTC_WAKEUP请查阅网上相关资料;
这里分享一下我的实测经验,如上述代码注释所述,最后我采用了setInexactRepeating方法,但是该方法也没有办法做到绝对可靠,我这里设置的是5分钟,实测结果绝大部分时间都是按照5分钟的间隔,进行周期性唤醒的,但偶尔也会出现6分钟,7分钟的唤醒间隔。如果设置为2分钟,则唤醒间隔更加参差不齐,基本会是2分钟、3分钟的交错出现。

原创粉丝点击