java – Android set()和setExact()以不正确的间隔触发警报

我正在开发一个应该每60秒执行一次任务的应用程序.由于 Android 4.4中的警报存在一些准确性问题,其中所有警报都不准确,我选择了链式模型:broadcastReceiver触发第一个警报,每个警报依次设置下一个警报.

问题是,即使我以60秒(60000毫秒)的间隔设置警报,警报也会以5秒的间隔触发,有时甚至更少.我已经在我的Nexus 5(Android 5.1.1)和Android 5.0.1仿真器上测试了代码,两者都给出了相同的结果.
我应该指出,两个接收器都在AndroidManifest上注册,我的应用程序具有RECEIVE_BOOT_COMPLETED权限.

编辑:setExact()导致完全相同的问题

StartupReceiver.java(broadcastReceiver for BOOT_COMPLETED):

public class StartupReceiver extends broadcastReceiver {
    @Override
    public void onReceive(Context context,Intent intent) {
        Log.d(TAG,"Got the BOOT_COMPLETED signal");
        // Get the first alarm to be invoked immediately
        AlarmReceiver.setNextScanAlarm(context,0);
    }
}

AlarmReceiver.java

public class AlarmReceiver extends broadcastReceiver {
    @Override
    public void onReceive(Context context,Intent intent) {
        // Start the service
        Intent startServiceIntent = new Intent(context,BackgroundService.class);
        startServiceIntent.putExtra("interval",60000);
        startServiceIntent.putExtra("action","scan");
        context.startService(startServiceIntent);

        // Schedule the next alarm
        setNextScanAlarm(context,60000);
    }

    public static void setNextScanAlarm(Context context,int interval) {
        Intent scanIntent = new Intent(context,AlarmReceiver.class);
        scanIntent.putExtra("interval",interval);
        scanIntent.putExtra("action","scan");
        PendingIntent pendingIntent = PendingIntent.getbroadcast(
                context,scanIntent,PendingIntent.FLAG_ONE_SHOT);


        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(
                AlarmManager.ELAPSED_REALTIME_WAKEUP,interval,pendingIntent);
    }
}

可能是什么问题呢?

解决方法

我相信因为这是一个叫闹钟
alarmManager.set(
                AlarmManager.ELAPSED_REALTIME_WAKEUP,pendingIntent);

你正在调用的变量是你想要在下一个警报中消失的时间,但是当你想到这个时候知道什么时候开始?更重要的是,时间何时实际上等于零?当你创建它?不.当你打电话给.set()?不,它在BOOT上实际上是零.所以你要求它在启动后60秒启动,并且你每次都要求这个,这个时间已经过去了.

这就是混乱的地方,你应该只使用像new这样的电话
Handler.postDelayed(Runnnable r,60000)而不是报警管理器.它将更准确,并且在理解Android操作系统及其警报/时钟/等等时不会遇到一些问题.

但是对于您的具体情况,我相信您可以通过访问系统函数调用/变量来解决它.所以在你的函数setNextScanAlarm()里面我相信它看起来像这样:

public static void setNextScanAlarm(Context context,int interval) {
        //create the intent the same way as before
        Intent scanIntent = new Intent(context,PendingIntent.FLAG_ONE_SHOT);

        //create new variables to calculate the correct time for this to go off
        long timeRightNow = System.elapsedRealTime() //use something else if you change AlarmManager type
        long timeWhenIShouldGoOff = timeRightNow + interval;

        //use the new timeWhenIShouldGoOff variable instead of interval
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(
                AlarmManager.ELAPSED_REALTIME_WAKEUP,timeWhenIShouldGoOff,pendingIntent);
    }

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...