简体   繁体   English

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

[英]AlarmManager Bug while Resetting/Cancelling Alarm on Date and Time Change

I want to send data to server at some regular interval. 我想regular向服务器发送数据。 So, I am using AlarmManager for the same. 所以,我正在使用AlarmManager It works fine but the problem is that when I cancel the Alarm on Date/Time change. 它工作正常但问题是当我cancel Date/Time更改时的警报。 At that time Alarm fires again before getting cancelled, so that makes my application worse as an extra data is sent to server with irregular interval. 此时警报在被取消之前再次触发,因此会使我的应用程序变得更糟,因为extra数据会以irregular间隔发送到server

Here is my BroadCastReceiver class with AlarmManager . 这是我的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;
            }
        }
    }
}

Below is the Screen Shot with Logcat output that explains that after cancelling the Alarm it fires once more time just after cancelling. 下面是带有Logcat输出的屏幕截图,解释了在取消警报后,它会在取消后再次触发。

在此输入图像描述

As you can see in the Logcat output black arrow shows where I changed that time to cancel the Alarm and red arrow shows that after cancelling the Alarm once again it fired just before cancelling which should not happen. 正如您在Logcat输出中看到的Logcat black arrow显示我在哪里更改了取消警报的时间, red arrow显示在再次取消警报后,它在取消之前触发,这不应该发生。 So, can anyone give my idea why that is happening and what should I do to restrict Alarm getting fired again before cancelling. 所以,任何人都可以给出我的想法为什么会发生这种情况,我应该怎么做才能restrict警报在取消之前再次被触发。

NOTE:- This only happens when I tried to increase date/time say from 10:00 to 11:00, works perfect when I decrease time say 10:00 to 9:00. 注意: - 只有在我尝试从10:00到11:00增加日期/时间时才会发生这种情况,当我减少10:00到9:00的时间时工作正常。

Not able to see the LogCat at my end, but looking at the code, I am not sure, how is the Service which gets invoked (TestService) gets killed / stopped ? 我不能在我的最后看到LogCat,但看着代码,我不确定,被调用的服务(TestService)是如何被杀死/停止的? I think you would need to stop it somehow. 我想你需要以某种方式阻止它。 Also, its not recommended to do long running tasks within the broadcast receiver. 此外,不建议在广播接收器内执行长时间运行的任务。 Have you verified that you service stop event is occuring after the mgr.cancel(pi) is fired? 您是否已经确认在mgr.cancel(pi)被解雇后发生服务停止事件?

Just try with some unique code with pending intent within activity and then cancel that intent using the same code. 只需在活动中尝试一些具有待定意图的唯一代码,然后使用相同的代码取消该意图。

setting pending intent in activity 在活动中设置待定意图

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

for stopping that broadcast receiver 用于停止该广播接收器

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

why that is happening 为什么会这样

First Thing is that you are using Intent Action android.intent.action.TIME_SET so It does mean that Everytime any how if the System date/time gets Changed your BroadcastReceiver will ne called Automatically. 第一件事就是你正在使用Intent Action android.intent.action.TIME_SET所以它确实意味着Everytime任何如果系统日期/时间如何变化您的BroadcastReceiver将自动调用

Second you have used one static boolean flag in your Receiver class. 其次,您在Receiver类中使用了一个static boolean flag Now what is happening is Whenever you change your System timings the flag toggles it's state from false to true and from true to false . 现在发生的事情是每当你改变你的系统时间时,标志就会将状态从false to true切换false to true ,从true to false

That is what exactly happening in your code and logcat also shows the same that everything is working as per the code written. 这就是你的代码中正好发生的事情,而logcat也显示了一切都按照编写的代码工作。

So according to me there is nothing Wrong happening in the code and it's output. 所以根据我的说法,代码中没有任何错误发生,它的输出。

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

First thing as I think, you should not use Action TIME_SET like that to toggle flag on/off as users and developers might not remember for what they are changing time either to turn FLAG On or Off, 首先,我认为,你不应该像这样使用Action TIME_SET来打开/关闭标志,因为用户和开发人员可能不记得他们正在改变时间要么打开或关闭FLAG,

Better way is that, you should handle the Service yourself by an Activity and show one ToggleButton there to manage the State of the FLAG and set and cancel the PendingIntent. 更好的方法是 ,您应该通过Activity自己处理服务并在那里显示一个ToggleButton来管理FLAG的状态并设置和取消PendingIntent。

OR And If you want to do the task of your service automatically then you just simply use the AlarmManager and set your Alarm Triggering time and Interval there only once say time is currenttime and Interval is 50000 miliseconds.. 或者如果您想自动完成服务任务, 那么您只需使用AlarmManager并设置警报触发时间和间隔,只有一次说时间是当前时间,间隔是50000毫秒。

so it will obviously call the service from now onwards after every 5mins, then in your App you will only require one ToggelButton to indciate the Sync to ther server is On or Off , if user Toggle it on or off then write your AlarmManager code there in your Activity only in the toggleButtontb.setOnCheckedChangeListener(listener) , I suppose this is the better way then what you are actually implementing. 所以它显然会在每5分钟后从现在开始调用该服务,然后在你的应用程序中你只需要一个ToggelButton来指示同步到服务器是开还是关 ,如果用户打开或关闭它然后在那里写你的AlarmManager代码你的活动只在toggleButtontb.setOnCheckedChangeListener(listener) ,我想这是你实际实现的更好的方式

I don't understand what need to set the receiver for date change if your goal is only to send the data on server in some regular interval . 如果您的目标只是在某个定期间隔内在服务器上发送数据,我不明白需要为日期更改设置接收器。

change date and time of device does not mean that your alarm wont work at that time which you already have set before those changes . 更改设备的日期和时间并不意味着您的警报在您更改之前已经设置的那个时间不起作用。 Alarmmanager work on that given duration of time which is excluding from local current date and time of device . Alarmmanager在给定的持续时间内工作,该时间不包括设备的当地当前日期和时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM