1

У меня есть две кнопки save and set alarm и cancel 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); 

Код внутри кнопки отмены 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 впервые он показывает

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

Однако, как я есть cancel тоже я могу нажать, что для отмены alarm.So я нажмите кнопку cancel и это показывает

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

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

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

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

Вопрос

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

P.S

Я говорил много постов как 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 я получил это работает now.Please увидеть его ответ.Я также должен был изменить

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. Я не знаю об этой проблеме!

ответ

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 documentation о PendingIntent.FLAG_NO_CREATEявляется неправильным! Он говорит:

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

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

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

+0

Извините, не понимаю, почему вы получаете NullPointerException. Я также не понимаю, почему вам нужно использовать один и тот же «PendingIntent» в обоих блоках. Пожалуйста, объясни. –

+0

Извините, до сих пор не понимаю проблему. Вы можете создать 'PendingIntent' вне' onCreate() '. Однако вы не можете создать ничего, что требует «Контекст», пока компонент не будет инициализирован (т. Е.: ** после того, как 'onCreate()' был вызван **). Кроме того, вам не нужно использовать один и тот же объект PendingIntent. Если вы вызываете 'PendingIntent.getBroadcast()' с тем же набором параметров, вы получите ссылку на тот же 'PendingIntent'. Если вы говорите, что попробовали, и это не сработало, добавьте пересмотренный код в исходный вопрос, чтобы мы могли посмотреть на него. –

+1

Я добавил примеры кода в свой ответ. Надеюсь, теперь это ясно. Вы можете создать 'PendingIntent' вне' onCreate() '. Вы можете поместить его другим способом. Вы просто не можете этого сделать ** перед вызовом 'onCreate()' (т. Е. В конструкторе или в статическом инициализаторе). Но вам все равно не нужно это делать. –

Смежные вопросы