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 Context
that 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
All your mucking around with
Context
is causing your problem. You absolutely positively cannot do this:a
static
variable gets initialized when the class is loaded. At this time, you have no idea whatContextBitchApp.getContext()
will return.In any case, you don't need to try to save
Context
and all that. Just always usegetApplicationContext()
when you need aContext
to pass as a parameter toPendingIntent.getBroadcast()
.Also, after calling
AlarmManager.cancel()
, you can also cancel thePendingIntent
by callingcancel()
on it.I am using 0 instead
PendingIntent.FLAG_UPDATE_CURRENT
and cancel method work fine, Try to use 0 in both intents or try to setPendingIntent.FLAG_CANCEL_CURRENT
to the pending intent in yourprivate void cancelAlarm(Context context)
method.