Кнопка «Отмена» будильника работает неправильно

1

У меня есть 2 кнопки, которые save and set alarm и cancel alarm который предназначен именно для того, что они предлагают.

Внутри объявленных переменных

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);

Код внутри кнопки Отмена onClickListener

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 в первый раз, она показывает

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

Однако, поскольку я cancel слишком, я могу нажать, чтобы отменить будильник. Так что я нажимаю кнопку cancel, и она показывает

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

который кажется правильным. Но когда я снова нажимаю кнопку " save, она показывает

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

что означает, что кнопка cancel не делает то, что она должна делать, хотя она выполняет toast для this alarm will be deleted.. Это снова означает, что должна быть какая-то проблема с alarmManager.cancel(sender1).

Вопрос

Что нужно изменить в коде для правильной работы кнопки cancel?

PS

Я упоминал много сообщений, как это, но не могу понять, в чем заключается конкретная проблема в моем случае.

Обновленный код

Кнопка отмены

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-pendingintent
alarmmanager
android-alarms

1 ответ

4
Лучший ответ

Здесь несколько вещей не так:

1 Не используйте Intent.FILL_IN_DATA в вызове PendingIntent.getBroadcast(). Это флаг Intent а не флаг PendingIntent. Он здесь не принадлежит.

2 Когда вы используете PendingIntent.FLAG_NO_CREATE это вернет null если PendingIntent еще не существует. В вашем коде для установки alarmUp у вас есть сравнение против null назад. ПРИМЕЧАНИЕ. См. Мои комментарии в конце этого ответа о том, что документация для этого неверна

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, потому что вы уже создали PendingIntent в onCreate().

ПРИМЕЧАНИЕ. PendingIntent создается, когда вы вызываете PendingIntent.getBroadcast(), а не при настройке будильника.


EDIT: добавьте примеры кода

Как я сказал ранее, вы не можете создать 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);
    ...

EDITED снова исправил несоответствие документации с помощью PendingIntent.FLAG_NO_CREATE:

Примечание. Похоже, что документация Android о PendingIntent.FLAG_NO_CREATE неверна! В нем говорится:

Флаг, указывающий, что если описанный PendingIntent уже существует, просто возвращайте null вместо его создания.

но это наоборот. Этот метод вернет PendingIntent если он уже существует. Он вернет null если он еще не существует.

Я отредактировал свой ответ, чтобы отразить правильную работу этого флага.

  • 0
    Извините, не понимаю, почему вы получаете NullPointerException. Я также не понимаю, почему вы должны использовать один и PendingIntent же PendingIntent в обоих блоках. Пожалуйста, объясни.
  • 0
    Извините, до сих пор не понимаю проблему. Вы можете создать PendingIntent вне onCreate() . Однако вы не можете создать ничего, что требует Context пока компонент не будет инициализирован (то есть: после onCreate() ). Кроме того, вам не нужно использовать один и тот же объект PendingIntent . Если вы PendingIntent.getBroadcast() с тем же набором параметров, вы получите ссылку на тот же PendingIntent . Если вы говорите, что пробовали, но это не сработало, добавьте пересмотренный код в исходный вопрос, чтобы мы могли на него посмотреть.
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню