在日期和时间更改时重置/取消警报时的 AlarmManager 错误

Posted

技术标签:

【中文标题】在日期和时间更改时重置/取消警报时的 AlarmManager 错误【英文标题】:AlarmManager Bug while Resetting/Cancelling Alarm on Date and Time Change 【发布时间】:2012-02-25 20:24:50 【问题描述】:

我想以regular 的时间间隔向服务器发送数据。所以,我同样使用AlarmManager。它工作正常,但问题是当我cancel Date/Time 上的警报发生变化时。那时,警报在被取消之前再次触发,这使我的应用程序变得更糟,因为extra 数据以irregular 间隔发送到server

这是我的BroadCastReceiver 类和AlarmManager

 public class MyReceiver extends BroadcastReceiver

    AlarmManager mgr;
    PendingIntent pi;
    Intent intent;
    public static boolean flag = false;

    @Override
    public void onReceive(final Context arg0, Intent arg1) 

        if(arg1.getAction().equals("android.intent.action.TIME_SET"))
            Log.d("MyReceiver", "Time set");

            mgr = (AlarmManager) arg0.getSystemService(Context.ALARM_SERVICE);
            intent = new Intent(arg0, TestService.class);
            intent.putExtra("test", "testvalue");
            pi = PendingIntent.getService(arg0, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

            if(!flag)
                mgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, 5000, pi);
                flag = true;
            
            else
                mgr.cancel(pi);
                pi.cancel();
                flag = false;
            
        
    

下面是带有 Logcat 输出的屏幕截图,它解释了在取消警报后,它会在取消后再次触发一次。

正如您在Logcat 输出中看到的那样,black arrow 显示了我更改取消警报的时间,red arrow 显示再次取消警报后它在取消之前触发,这是不应该发生的。那么,任何人都可以告诉我为什么会发生这种情况以及我应该怎么做restrict警报在取消之前再次被触发。

注意:- 只有当我尝试将日期/时间从 10:00 增加到 11:00 时才会发生这种情况,当我将时间减少到 10:00 到 9:00 时效果很好。

【问题讨论】:

【参考方案1】:

无法在我的最后看到 LogCat,但查看代码,我不确定,被调用的服务 (TestService) 是如何被杀死/停止的?我认为你需要以某种方式阻止它。此外,不建议在广播接收器中执行长时间运行的任务。 您是否验证了在触发 mgr.cancel(pi) 后您的服务停止事件正在发生?

【讨论】:

我没有停止服务我只是重置警报。 我猜也尝试停止服务。因为在取消警报管理器时服务可能仍在工作。 我不认为是这种情况,因为正如我所说,它只会在我增加时间时发生,而在我减少时间时工作正常。【参考方案2】:

只需尝试在活动中使用一些具有待处理意图的唯一代码,然后使用相同的代码取消该意图。

在活动中设置待处理意图

PendingIntent.getBroadcast(this, code, intent, PendingIntent.FLAG_UPDATE_CURRENT);

用于停止广播接收器

PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), code, intent, 0); AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE); alarmManager.cancel(pendingIntent);

【讨论】:

【参考方案3】:

为什么会这样

第一件事是您正在使用 Intent Action android.intent.action.TIME_SET,所以这确实意味着 如果系统日期/时间发生更改,您的 BroadcastReceiver 将自动调用

第二次你在Receiver 类中使用了一个static boolean flag。 现在发生的事情是,每当您更改系统计时,标志就会从false to truetrue to false 切换它的状态

这正是您的代码中发生的事情,logcat 也显示出同样的情况:一切都按照编写的代码运行。

所以在我看来,什么都没有代码和输出中发生了错误。

what should I do to restrict Alarm getting fired again before cancelling

我认为的第一件事是,您不应该像这样使用 Action TIME_SET 来打开/关闭标志,因为用户和开发人员可能不记得他们是什么更改时间以打开或关闭 FLAG,

更好的方法是, 您应该通过 Activity 自己处理服务,并在那里显示一个 ToggleButton 来管理 FLAG 的状态并设置和取消 PendingIntent。

如果您想自动执行您的服务的任务,您只需使用AlarmManager 并设置您的警报触发时间和间隔只有一次说时间是当前时间,间隔是 50000 毫秒..

所以它显然会从现在开始每 5 分钟调用一次服务,然后在您的应用程序中,如果用户切换它,您只需要一个 ToggelButton 来指示与服务器的同步是 On 还是 Off打开或关闭然后在您的活动中编写您的 AlarmManager 代码仅在 toggleButtontb.setOnCheckedChangeListener(listener) 中,我想 这是更好的方法然后是您实际实施的方法。

【讨论】:

我无法使用 ToggleButton,因为我的应用程序中没有任何 GUI。另外我想强制使用TIME_SET,并在时间变化时触发一段代码。【参考方案4】:

如果您的目标只是定期在服务器上发送数据,我不明白需要设置接收器以更改日期。

更改设备的日期和时间并不意味着您的闹钟不起作用 在这些更改之前您已经设置的那个时间。Alarmmanager 在给定的持续时间内工作,不包括设备的本地当前日期和时间。

【讨论】:

我从用户的角度考虑如果用户更改日期和时间。 如果您设置的闹钟不会取消但用户会更改它,它会保持原样 我知道它不会取消,但问题是当用户更改日期和时间时,服务第一次被多次调用。 如果您的目标只是定期在服务器上发送数据,我不明白需要设置接收器以更改日期。

以上是关于在日期和时间更改时重置/取消警报时的 AlarmManager 错误的主要内容,如果未能解决你的问题,请参考以下文章

按钮更改输入时的警报文本[重复]

Ionic2 x Angular:导航更改时的服务重置

取消之前设置的警报

SQL查询返回列更改时的最新日期

如何在 crontab 更改时获得警报?

Bootstrap 日期范围选择器移动突出显示更改日期时的前一个日期