1

I have 2 buttons save and set alarm and cancel alarm which are meant to do exactly what they suggest.

Inside onCreate declared variables

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

Code inside Cancel Button 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();
                                }

Code for save button

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

When i click save for the first time it shows

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

However as i have cancel too i can click that to cancel the alarm.So i click cancel button and it shows

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

which seems right.But when i again click save button it shows

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

which means the cancel button is not doing what it should do although it executes the toast for this alarm will be deleted..Which again means there must be some problem with alarmManager.cancel(sender1).

Question

What to modify in the code to get the cancel button work correctly?

P.S

I referred many posts like this but can't get what's the exact problem in my case.

Updated Code

For cancel button

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

For Save Button

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

This results in same as previous.Cancel button doesn't seem to work.

Solution

Thanks to @David Wasser i got it working now.Please see his answer.I also had to change

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

to

boolean alarmUp = (PendingIntent.getBroadcast(AlarmActivity.this, 2, alarmintent,PendingIntent.FLAG_NO_CREATE) != null) in both the blocks.

But as developer.android.com says FLAG_NO_CREATE Flag indicating that if the described PendingIntent already exists, then simply return null instead of creating it.I don't know about this issue!

Cœur
  • 37,241
  • 25
  • 195
  • 267
Sash_KP
  • 5,551
  • 2
  • 25
  • 34

1 Answers1

4

Several things are wrong here:

1 Don't use Intent.FILL_IN_DATA in the call to PendingIntent.getBroadcast(). This is an Intent flag and not a PendingIntent flag. It doesn't belong here.

2 When you use the PendingIntent.FLAG_NO_CREATE this will return null if the PendingIntent doesn't already exist. In your code to set alarmUp you've got the comparison against null backwards. NOTE: See my comments at the end of this answer about the fact that the documentation for this is wrong

3 In your onCreate() you are doing this:

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

This line will create the PendingIntent even if you don't set an alarm with it. Later, when you check if the PendingIntent exists with this code:

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

alarmUp will always be false, because you have already created the PendingIntent in onCreate().

NOTE: The PendingIntent is created when you call PendingIntent.getBroadcast(), not when you set the alarm.


EDIT: Add more code examples

As I said earlier, you can't create the PendingIntent if you want to use it to determine whether the alarm is set or not. You must first check if the PendingIntent exists and then you can create it to set/cancel it. To fix, do this:

In cancel button:

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

In save button:

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 again to fix documentation discrepancy with PendingIntent.FLAG_NO_CREATE:

Note: It seems the Android documentation about PendingIntent.FLAG_NO_CREATE is wrong! It says:

Flag indicating that if the described PendingIntent already exists, then simply return null instead of creating it.

but this is backwards. This method will return the PendingIntent if it already exists. It will return null if it doesn't already exist.

I've edited my answer to reflect the correct operation of this flag.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • Sorry, don't understand why you are getting NullPointerException. I also don't understand why you need to use same `PendingIntent` in both blocks. Please explain. – David Wasser Feb 02 '14 at 12:10
  • Sorry, still don't understand the problem. You can create a `PendingIntent` outside of `onCreate()`. However, you can't create anything that requires a `Context` until the component has been initialized (ie: **after `onCreate()` has been called**). Also, you don't need to use the same `PendingIntent` object. If you call `PendingIntent.getBroadcast()` with the same set of parameters you will get a reference to the same `PendingIntent`. If you say you've tried it and it didn't work, please add the revised code to your original question so we can look at it. – David Wasser Feb 02 '14 at 12:48
  • 1
    I added code examples in my answer. I hope this is now clear. You can create the `PendingIntent` outside of `onCreate()`. You can put it in another method. You just can't do it **before** `onCreate()` is called (ie: in the constructor or in a static initalizer). But you don't need to do that anyway. – David Wasser Feb 02 '14 at 13:39
  • Thanks a lot for your valuable suggestions.You're awesome.It was the issue there.But i had to change `PendingIntent.getBroadcast(AlarmActivity.this, 2,alarmintent,PendingIntent.FLAG_NO_CREATE) == null` to `PendingIntent.getBroadcast(AlarmActivity.this, 2,alarmintent,PendingIntent.FLAG_NO_CREATE) != null` in both the blocks!But [developer.android.com](http://developer.android.com/reference/android/app/PendingIntent.html#FLAG_NO_CREATE) says it should return `null` if `pendingintent` already exists!Is it a bug? – Sash_KP Feb 02 '14 at 14:22
  • Good point. I didn't see that. I'll need to check that myself. – David Wasser Feb 02 '14 at 14:28
  • I did accept your answer and also edited my post.Please check my edit.And Please edit your answer what you think about the `!null` issue after checking. – Sash_KP Feb 02 '14 at 14:33
  • 1
    You are absolutely right. The documentation is wrong! It never ceases to amaze me that the docs contain incorrect information for so long. I'll edit my answer as well. – David Wasser Feb 02 '14 at 14:38
  • 1
    @A.Adam please post a new question with your code. This isn't the right place to ask a new question. – David Wasser Jul 28 '15 at 18:21