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

标签 java android alarmmanager

我正在开发一款应每 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(BOOT_COMPLETED 的 BroadcastReceiver):

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,
                0,
                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,
                interval,
                pendingIntent);

您正在调用的变量 interval 是您希望在下一个警报之前耗时量,但是当您考虑这个时,它知道什么时候开始?更重要的是,什么时候时间实际上等于零?

你什么时候创造它?没有。
当你调用.set()时?否。

实际上在开机时为零。所以你要求它在启动后 60 秒启动,而你每次都这样要求,这个时间已经过去了。

这就是困惑所在,您可能应该只使用像 new 这样的调用 Handler.postDelayed(Runnnable r, 60000) 而不是警报管理器。它将更加准确,并且不会因理解 Android 操作系统及其闹钟/时钟/等等而受到一些问题的影响。

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

   public static void setNextScanAlarm(Context context, int interval) {
        //create the intent the same way as before
        Intent scanIntent = new Intent(context, AlarmReceiver.class);
        scanIntent.putExtra("interval", interval);
        scanIntent.putExtra("action", "scan");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                context,
                0,
                scanIntent,
                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);
    }

关于java - Android set() 和 setExact() 警报以不正确的时间间隔触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30149047/

相关文章:

java - 注入(inject)的 MessageSource 为 null

android - NotificationCompat.Builder 缺少 build() 方法

Android NotificationListenerService 后台执行限制/Doze

java - Spring MVC 3 - 使用 404 响应请求?

java - LibGDX 有动画 Actor 吗?

Java 枚举处理

Android Action Bar SearchView 菜单图标大小

android - 如何将单选按钮对齐到关联文本的右侧?

java - Hello World 根本不会加载到 Android 虚拟设备上。为什么?

android - 泄露 Intent 和警报管理器