1

I have created an alarm with a notification and a button to stop the alarm but it seems that there is some issue with the Contextthat I have to get in order to cancel the AlarmManager.

I have researched a lot and I think I have applied most of the things I found but somehow can't get this to work.

I am aware the PendingIntent has to be the same and it appears to me they are with the same request codes too.

AlarmSlave.class - Sets Alarm

 public class AlarmSlave /*extends Service*/ {

    private static final String STOP_ACTION = "STOP";

    private int hourOfDay;
    private int minuteOfHour;


    private AlarmManager alarmManager;
    private PendingIntent pendingIntent;

    public AlarmSlave() {

    }
AlarmSlave(int hour, int minute) {

        hourOfDay = hour;
        minuteOfHour = minute;

    }

    public void setAlarm(Context context) {

        alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        /*Intent intent = new Intent(context, AlarmReceiver.class);*/
        pendingIntent = PendingIntent.getBroadcast(context, 327, new Intent(context, AlarmReceiver.class), 0);

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
        calendar.set(Calendar.MINUTE, minuteOfHour);
        alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);

        Log.d("Ctx setAlarm ", context.toString());

    }

AlarmReceiver.class - Plays Ringtone Pretty Much.

    public class AlarmReceiver extends WakefulBroadcastReceiver{

    @Override
    public void onReceive(final Context context, Intent intent){

        /*MainActivity inst = MainActivity.instance();

        Log.d("Testing","this is here"+inst);*/

        Uri alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
        if (alarmUri == null){
            alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
        }

        Ringtone ringtone = RingtoneManager.getRingtone(context, alarmUri);
        ringtone.play();


        ComponentName componentName = new ComponentName(context.getPackageName(), AlarmService.class.getName());
        startWakefulService(context, (intent.setComponent(componentName)));
        setResultCode(Activity.RESULT_OK);
    }
}

AlarmService.class - This is what shows the notification, the content intents are working fine but for the action they are not.

    public class AlarmService extends IntentService {

    public static final String STOP_ACTION = "STOP";

    public AlarmService() {
        super("AlarmService");
    }


    @Override
    public void onHandleIntent(Intent intent) {
        sendNotification("Wake Up! Wake Up");
    }

    private void sendNotification(String msg) {
        Log.d("AlarmService", "Preparing to send notification...:" + msg);
        NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);

        //PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 327, new Intent(getApplicationContext(), AlarmActivity.class), 0);
        int notificationId = 1; // just use a counter in some util class...
        PendingIntent dismissIntent = AlarmActivity.getDismissIntent(notificationId, getApplicationContext());

        /*Intent stopIntent = new Intent(this, AlarmSlave.class);
        stopIntent.setAction(STOP_ACTION);

        PendingIntent stopPendingIntent = PendingIntent.getBroadcast(this, 10, stopIntent, 0);*/

        NotificationCompat.Builder alarmNotificationBuilder = new NotificationCompat.Builder(getApplicationContext())
                .setContentTitle("Alarm")
                .setSmallIcon(R.mipmap.ic_launcher_round)
                .setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
                .setContentText(msg)
                .addAction(R.mipmap.ic_launcher_round, "STOP", dismissIntent);

        alarmNotificationBuilder.setContentIntent(dismissIntent);
        notificationManager.notify(1, alarmNotificationBuilder.build());

        Log.d("AlarmService", "Notification Sent");
    }
}

ContextApp.class - This is what generates Context for me.

public class ContextBitchApp extends Application {

 private static Context mContext;

@Override
public void onCreate(){
    super.onCreate();
    mContext = getApplicationContext();
}

public static Context getContext(){
    return mContext;


   }
}

Pardon for some of the language in the naming, done out of utter frustration after trying several different things over the period of two days.

EDIT: This is what my Log is showing for Context

05-13 09:37:55.208 24235-24235/<omitted> D/Ctx setAlarm: <omitted>.ContextBitchApp@7709bb7
05-13 09:41:18.760 3244-3244/<omitted>:remote D/Ctx onReceive: android.app.ReceiverRestrictedContext@2c317d9
05-13 09:41:18.760 3244-3244/<omitted>:remote D/Ctx cancelAlarm: android.app.ReceiverRestrictedContext@2c317d9

EDIT: Updated Code

4127157
  • 1,438
  • 2
  • 15
  • 28
  • May I know why you are not using 'ctx' as context again in 'cancelAlarm()' as you do in 'setAlarm()'? In my opinion that's the only problem. – kush gupt May 13 '17 at 12:50
  • @kushgupt In the `AlarmService`class I have called the `Context` form `AlarmSlave` to try to have the same `Context` but the log still returns different. – 4127157 May 13 '17 at 16:41
  • Okay,( so what I have learnt so far from your code), I think the problem with your code is that you are using different kind of context, like you are using `getApplicationContext` in your `public class ContextBitchApp` and used that @`setAlarm()` method of `public class AlarmSlave` class, but I didn't see what context you use for `cancelAlarm`, clearly it's not the same application context. So this means you are creating two different Intent which results in different pending intent, and ultimately you cannot cancel the same alarm. This is my opinion. – kush gupt May 13 '17 at 17:59
  • So have a look at his question: [When to call activity context OR application context?](http://stackoverflow.com/questions/7298731/when-to-call-activity-context-or-application-context) – kush gupt May 13 '17 at 17:59
  • @kushgupt I am using the same way to get context just that I am passing a copy of the same Context from `AlarmSlave` to `AlarmService`, I am retrieving from `ContextBitchApp` and passing the same to `AlarmService` through `AlarmSlave` using the `getAlarmSlaveContext()` – 4127157 May 13 '17 at 20:00
  • can you try 'ctx' context in 'cancelAlarm()'? I believe it will sort out your problem and you can easily do that since they are both the members of the same class. – kush gupt May 14 '17 at 12:46

2 Answers2

0

I am using 0 instead PendingIntent.FLAG_UPDATE_CURRENT and cancel method work fine, Try to use 0 in both intents or try to set PendingIntent.FLAG_CANCEL_CURRENT to the pending intent in your private void cancelAlarm(Context context) method.

Pavel Poley
  • 5,307
  • 4
  • 35
  • 66
0

All your mucking around with Context is causing your problem. You absolutely positively cannot do this:

private static  Context ctx = ContextBitchApp.getContext();
private static final Context ctxCopy = ctx;

a static variable gets initialized when the class is loaded. At this time, you have no idea what ContextBitchApp.getContext() will return.

In any case, you don't need to try to save Context and all that. Just always use getApplicationContext() when you need a Context to pass as a parameter to PendingIntent.getBroadcast().

Also, after calling AlarmManager.cancel(), you can also cancel the PendingIntent by calling cancel() on it.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • `Can't resolve method 'getApplicationContext()'` is what it is showing me in `AlarmSlave.class` , – 4127157 May 15 '17 at 03:20
  • If you are calling this from `onReceive()`, use `context.getApplicationContext()`. – David Wasser May 15 '17 at 11:53
  • @4127157 Were you able to figure this out? What is the status of your problem? – David Wasser May 26 '17 at 13:00
  • I have updated the code, please have a look, I can send you the .ZIP too if you'd like that. The alarm notification is going but the ringtone is not and not sure if alarm is cancelling now or not. – 4127157 May 30 '17 at 20:42
  • And what does `PendingIntent dismissIntent = AlarmActivity.getDismissIntent(notificationId, getApplicationContext())` do? You didn't show that code. – David Wasser Jun 06 '17 at 10:40