У меня есть 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.
Я не знаю об этой проблеме!
Здесь несколько вещей не так:
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
если он еще не существует.
Я отредактировал свой ответ, чтобы отразить правильную работу этого флага.
PendingIntent
жеPendingIntent
в обоих блоках. Пожалуйста, объясни.PendingIntent
внеonCreate()
. Однако вы не можете создать ничего, что требуетContext
пока компонент не будет инициализирован (то есть: послеonCreate()
). Кроме того, вам не нужно использовать один и тот же объектPendingIntent
. Если выPendingIntent.getBroadcast()
с тем же набором параметров, вы получите ссылку на тот жеPendingIntent
. Если вы говорите, что пробовали, но это не сработало, добавьте пересмотренный код в исходный вопрос, чтобы мы могли на него посмотреть.