使用AlarmManager不准时的解决方法

        最近我们公司的产品被客户投诉定时关机偶现不准时和偶现不起作用的问题。具体复现操作是定时一段比较长的时间进行自动关机就很容易出现该概率问题。

        由于这个定时关机功能是前同事实现的,所以我得查看代码,查看跟踪代码发现该定时方式使用的是使用了AlarmManager里的set()方法:

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, setTime, pendingIntent);

        我自己调试了发现短时间的定时是可以正常实现功能的,然后调了一个十个小时的定时关机发现确实有误差,延迟了三分钟才关机。 

查阅文档等资料:

        官方文档提示API19(android4.4)开始, 为了节能省电(减少系统唤醒和电池使用)。使用Alarm.set()和Alarm.setRepeating()已经不保证精确性。API19版本以上应该使用另外两个精确的Alarm方法,setWindow()和setExact()。

但是在Android8.0中使用了setExact()方法后还是发现长时间定时会不准时,继续查阅资料发现官方在API23(android6.0)后添加了新的应用接口:

 然后耐心的将接口方法改为setExactAndAllowWhileIdle()。

        但是奇葩的事情还是出现了,在Android8.0中使用该接口后设置十个小时长时间定时,然后息屏放置,发现还是会出现不准时的问题,延迟了足足两分钟。

        此时已经没有耐心了,果断决定换一种实现方式,不使用AlarmManager去定时了,稳定性实在令人堪忧。

解决方法

最后使用轮询去比较设定的关机时间和当前时间。

        在这里我采取注册监听 ACTION_TIME_TICK这个系统广播,系统会在每隔一分钟发送一个ACTION_TIME_TICK广播:

 

        每接收到一个广播就进行一次比较,将设定的关机时间戳和当前时间进行比较,如果比较的时间的绝对值小于60,就进行相应的操作。

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            final String action = intent.getAction();
           
            if (action.equals(ACTION_TIME_TICK)) {

             //setMillionSeconds为设定的定时时间戳
            if (Math.abs(setMillionSeconds - System.currentTimeMillis()) <= 60000) {

                //to do what you whant to do 

            }             
          }
        }
    };


        使用这种方式比使用AlarmManager稳定多了!AlarmManager设定的时间能不能回调回来就是一个玄学!

不过需要注意的是,ACTION_TIME_TICK广播需要动态注册

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值