【问题标题】:Alarm "cancel" button not working correctly警报“取消”按钮无法正常工作
【发布时间】:2014-02-02 08:38:32
【问题描述】:

我有 2 个按钮 save and set alarmcancel alarm,它们旨在完全按照他们的建议进行操作。

在 onCreate 内声明的变量

final Intent alarmintent = new Intent(AlarmActivity.this, AlarmReceiver.class);
final AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
final PendingIntent sender1 = PendingIntent.getBroadcast(getApplicationContext(), 2, alarmintent, PendingIntent.FLAG_UPDATE_CURRENT |  Intent.FILL_IN_DATA);

ClickListener 上的取消按钮内的代码

boolean alarmUp = (PendingIntent.getBroadcast(AlarmActivity.this, 2,alarmintent,PendingIntent.FLAG_NO_CREATE) == null);

if (alarmUp)
            {

                  new AlertDialog.Builder(AlarmActivity.this)
                  .setTitle("Alert")
                  .setMessage("This alarm will be deleted.")
                  .setPositiveButton("Ok", new DialogInterface.OnClickListener() {

                                    public void onClick(DialogInterface arg0, int arg1) {

                                        alarmManager.cancel(sender1);
                                        sender1.cancel();
                                        Toast.makeText(getApplicationContext(), "Alarm Cancelled.", Toast.LENGTH_LONG).show(); 
                                    }


                                })
                                .create().show();
                                }
                                else
                                {
                                    new AlertDialog.Builder(AlarmActivity.this)
                                    .setTitle("Alert")
                                    .setMessage("Alarm for this is not set yet.")
                                 .setPositiveButton("Ok",null)
                                .create().show();
                                }

保存按钮代码

boolean alarmUp = (PendingIntent.getBroadcast(AlarmActivity.this, 2, 
                             alarmintent, 
                                PendingIntent.FLAG_NO_CREATE) == null);


                        if (alarmUp)
                        {
                            //Log.d("myTag", "Alarm is already active");
                            new AlertDialog.Builder(AlarmActivity.this)
                            .setTitle("Alert")
                            .setMessage("Already an alarm is set for this particular time and day.")
                            .setPositiveButton("OK",null    
                            )

                            .create().show();
                        }
    Calendar c = Calendar.getInstance();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,c.getTimeInMillis()+5000,24 * 60 * 60 * 1000, sender1);

当我第一次单击save 时,它会显示

a http://www.4shared.com/download/puMWZEvRba/alert1.png

但是我也有cancel,我可以点击它来取消警报。所以我点击cancel按钮,它会显示

a http://www.4shared.com/download/1UOTyVK0ce/alert2.png

这似乎是对的。但是当我再次单击save 按钮时,它会显示

a http://www.4shared.com/download/puMWZEvRba/alert1.png

这意味着cancel 按钮没有做它应该做的事情,尽管它为this alarm will be deleted. 执行了toast。这再次意味着alarmManager.cancel(sender1) 一定有问题。

问题

要在代码中修改什么以使cancel 按钮正常工作?

附言

我提到了很多帖子,比如this,但我不知道我的具体问题是什么。

更新代码

取消按钮

final Intent alarmintent = new Intent(AlarmActivity.this, AlarmReceiver.class);
    final AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    final PendingIntent sender1 = PendingIntent.getBroadcast(getApplicationContext(), 2, alarmintent, PendingIntent.FLAG_UPDATE_CURRENT);
    boolean alarmUp = (PendingIntent.getBroadcast(AlarmActivity.this, 2,alarmintent,PendingIntent.FLAG_NO_CREATE) == null);

if (alarmUp)
            {

                  new AlertDialog.Builder(AlarmActivity.this)
                  .setTitle("Alert")
                  .setMessage("This alarm will be deleted.")
                  .setPositiveButton("Ok", new DialogInterface.OnClickListener() {

                                    public void onClick(DialogInterface arg0, int arg1) {

                                        alarmManager.cancel(sender1);
                                        sender1.cancel();
                                        Toast.makeText(getApplicationContext(), "Alarm Cancelled.", Toast.LENGTH_LONG).show(); 
                                    }


                                })
                                .create().show();
                                }
                                else
                                {
                                    new AlertDialog.Builder(AlarmActivity.this)
                                    .setTitle("Alert")
                                    .setMessage("Alarm for this is not set yet.")
                                 .setPositiveButton("Ok",null)
                                .create().show();
                                }   

保存按钮

 final Intent alarmintent = new Intent(AlarmActivity.this, AlarmReceiver.class);
                        final AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
                        final PendingIntent sender1 = PendingIntent.getBroadcast(getApplicationContext(), 2, alarmintent, PendingIntent.FLAG_UPDATE_CURRENT);

boolean alarmUp = (PendingIntent.getBroadcast(AlarmActivity.this, 2, 
                             alarmintent, 
                                PendingIntent.FLAG_NO_CREATE) == null);


                        if (alarmUp)
                        {
                            //Log.d("myTag", "Alarm is already active");
                            new AlertDialog.Builder(AlarmActivity.this)
                            .setTitle("Alert")
                            .setMessage("Already an alarm is set for this particular time and day.")
                            .setPositiveButton("OK",null    
                            )

                            .create().show();
                        }
    Calendar c = Calendar.getInstance();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,c.getTimeInMillis()+5000,24 * 60 * 60 * 1000, sender1);

这与之前的结果相同。Cancel 按钮似乎不起作用。

解决方案

感谢 @David Wasser 我现在可以正常工作了。请看他的回答。我也不得不改变

boolean alarmUp = (PendingIntent.getBroadcast(AlarmActivity.this, 2, alarmintent,PendingIntent.FLAG_NO_CREATE) == null)

boolean alarmUp = (PendingIntent.getBroadcast(AlarmActivity.this, 2, alarmintent,PendingIntent.FLAG_NO_CREATE) != null) 在两个块中。

但正如developer.android.com 所说FLAG_NO_CREATE Flag indicating that if the described PendingIntent already exists, then simply return null instead of creating it.我不知道这个问题!

【问题讨论】:

    标签: android alarmmanager android-pendingintent android-alarms


    【解决方案1】:

    这里有几处是错误的:

    1 不要在对PendingIntent.getBroadcast() 的调用中使用Intent.FILL_IN_DATA。这是Intent 标志而不是PendingIntent 标志。它不属于这里。

    2 当您使用 PendingIntent.FLAG_NO_CREATE 时,如果 PendingIntent 尚不存在,这将返回 null。在您设置alarmUp 的代码中,您已经与null 进行了比较。 注意:请参阅此答案末尾的我的 cmets,了解有关此问题的文档是错误的事实

    3 在您的onCreate() 中,您正在这样做:

    PendingIntent sender1 = PendingIntent.getBroadcast(getApplicationContext(), 2,
          alarmintent, PendingIntent.FLAG_UPDATE_CURRENT |  Intent.FILL_IN_DATA);
    

    此行将创建PendingIntent,即使您没有使用它设置警报。稍后,当您使用此代码检查 PendingIntent 是否存在时:

    boolean alarmUp = (PendingIntent.getBroadcast(AlarmActivity.this, 2, 
          alarmintent, PendingIntent.FLAG_NO_CREATE) == null);
    

    alarmUp 将始终为false,因为您已经在onCreate() 中创建了PendingIntent

    注意:PendingIntent 是在您调用 PendingIntent.getBroadcast() 时创建的,而不是在您设置闹钟时创建的。


    编辑:添加更多代码示例

    正如我之前所说,如果您想使用它来确定是否设置了警报,则无法创建PendingIntent。您必须首先检查PendingIntent 是否存在,然后您可以创建它来设置/取消它。要修复,请执行以下操作:

    取消按钮中:

    final Intent alarmintent = new Intent(AlarmActivity.this, AlarmReceiver.class);
    final AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    // Determine if the alarm has already been set
    boolean alarmUp = (PendingIntent.getBroadcast(AlarmActivity.this, 2,alarmintent,PendingIntent.FLAG_NO_CREATE) != null);
    if (alarmUp) {
        final PendingIntent sender1 = PendingIntent.getBroadcast(getApplicationContext(), 2, alarmintent, PendingIntent.FLAG_UPDATE_CURRENT);
        ...
    

    保存按钮中:

    final Intent alarmintent = new Intent(AlarmActivity.this, AlarmReceiver.class);
    final AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    // Determine if the alarm has already been set
    boolean alarmUp = (PendingIntent.getBroadcast(AlarmActivity.this, 2, alarmintent, PendingIntent.FLAG_NO_CREATE) != null);
    if (alarmUp) {
        final PendingIntent sender1 = PendingIntent.getBroadcast(getApplicationContext(), 2, alarmintent, PendingIntent.FLAG_UPDATE_CURRENT);
        ...
    

    再次编辑以修复与 PendingIntent.FLAG_NO_CREATE 的文档差异

    注意:关于PendingIntent.FLAG_NO_CREATEAndroid documentation 似乎是错误的! 它说:

    标志表示如果描述的PendingIntent已经存在, 然后只需返回 null 而不是创建它。

    但这是倒退的。如果 PendingIntent 已经存在,此方法将返回它。 如果 null 尚不存在,它将返回

    我已编辑我的答案以反映此标志的正确操作。

    【讨论】:

    • 抱歉,不明白为什么会收到 NullPointerException。我也不明白为什么你需要在两个块中使用相同的PendingIntent。请解释一下。
    • 对不起,还是不明白问题所在。您可以在onCreate() 之外创建PendingIntent。但是,在组件初始化之前,您不能创建任何需要Context 的东西(即:在调用onCreate() 之后)。此外,您不需要使用相同的 PendingIntent 对象。如果您使用相同的参数集调用PendingIntent.getBroadcast(),您将获得对相同PendingIntent 的引用。如果您说您已经尝试过但没有成功,请将修改后的代码添加到您的原始问题中,以便我们查看。
    • 我在回答中添加了代码示例。我希望这现在很清楚。您可以在onCreate() 之外创建PendingIntent。你可以把它换成另一种方法。 before onCreate() 被调用(即:在构造函数中或在静态初始化器中)你不能这样做。但无论如何你都不需要这样做。
    • 你是绝对正确的。文档有误!文档包含不正确的信息这么久让我感到惊讶。我也会编辑我的答案。
    • @A.Adam 请在您的代码中发布一个新问题。这里不适合提出新问题。
    猜你喜欢
    • 2021-01-17
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多