Search code examples
javaandroidpush-notificationalarmmanager

AlarmManager doesn't fire


my note app should remember my users with a notification at their note at a specific date and time the user had set. My Problem is that I don't get the notification at the set time.
This is my alarmManager.class (Here I create my Alarms)

public class alarmManager {

    public static void createAlarm(long timeInMillis, int requestCode, Intent i) {
        PendingIntent pi = PendingIntent.getService(MainActivity.context, requestCode, i, PendingIntent.FLAG_UPDATE_CURRENT);
        getAlarmManager().set(AlarmManager.RTC_WAKEUP, timeInMillis, pi);
    }

    public static void deleteAlarm(Intent i, int requestCode) {
        if (doesPendingIntentExist(MainActivity.context, i, requestCode)) {
            PendingIntent pi = PendingIntent.getService(MainActivity.context, requestCode, i, PendingIntent.FLAG_NO_CREATE);
            pi.cancel();
            getAlarmManager().cancel(pi);
        }
    }

    private static AlarmManager getAlarmManager() {
        return (AlarmManager) MainActivity.context.getSystemService(Context.ALARM_SERVICE);
    }

    private static boolean doesPendingIntentExist(Context context, Intent i, int requestCode) {
        PendingIntent pi = PendingIntent.getService(context, requestCode, i, PendingIntent.FLAG_NO_CREATE);
        return pi != null;
    }
}  

When the user creates a new note this lines get fired (They send everything is needed to my alarmManager.class)

Intent i = new Intent(MainActivity.context, NotificationService.class);
        i.putExtra(NotificationService.i_UID, id);
        i.putExtra(NotificationService.i_TEXT, title);
        i.putExtra(NotificationService.i_CONTENT, content);
        i.putExtra(NotificationService.i_REMINDEDATE, mUserReminderDate);
        i.putExtra(NotificationService.i_REPEAT, repeatAlarmSelectedOption);
        alarmManager.createAlarm(mUserReminderDate.getTime(), id.hashCode(), i);  

When everything works the NotificationService.class should get called at the chosen time. (Here the notification should show to the user)

public class NotificationService extends IntentService {
    public static final String i_UID = "uuid";
    public static final String i_TEXT = "title";
    public static final String i_CONTENT  = "content";
    public static final String i_REMINDEDATE = "remindeDate";
    public static final String i_REPEAT = "repeatAlarm";

    private String mTodoText, mTodoContent, mTodoUUID;
    private Date mTodoDate;
    private int mTodoRepeat;
    private Intent processIntent;

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

    @Override
    protected void onHandleIntent(Intent intent) {
        this.processIntent = intent;
        mTodoText = intent.getStringExtra(i_TEXT);
        mTodoContent = intent.getStringExtra(i_CONTENT);
        mTodoUUID = intent.getStringExtra(i_UID);
        mTodoDate = (Date) intent.getSerializableExtra(i_REMINDEDATE);
        mTodoRepeat = intent.getIntExtra(i_REPEAT, 0);

        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Notification notification = new Notification.Builder(this)
                .setContentTitle(mTodoText)
                .setContentText(mTodoContent)
                .setSmallIcon(R.drawable.app_logo_transparent_bg)
                .setAutoCancel(true)
                .setDefaults(Notification.DEFAULT_SOUND)
                .build();

        manager.notify(100, notification);
    }  

Unfortunately it doesn't work. No errors. No notification. Nothing.
I hope someone can help me.


Solution

  • In my opinion the problem is when you create a PendingIntent:

    PendingIntent pi = PendingIntent.getService(MainActivity.context, requestCode, i, PendingIntent.FLAG_UPDATE_CURRENT);
    

    To be absolutely sure, schedule an alarm, then run from adb following command: adb shell dumpsys alarm and search for your PendingIntent. If you find it, schedule one more time alarm and run command one more time. Look again for your pending intent and make sure it is a new one and try to search for this previous scheduled. If it is problem with PendingIntent you will find only the newest PendingIntent.

    Solution:
    Since AlarmManger while comparing PendingIntents doesn't compare extra data passed it, but compares request code, data, action and categories you need to change one of them every time you schedule a new alarm. My suggestion is to pass uri from database to every new scheduled PendingIntent. That will make each of them uniqal so the older one won't be cancelled when a new scheduled. To sum up, to argument i in your code call method setData() and pass uri as an argument. You can do it in a method or from a class where method is being called. It may look like that:

     public static void createAlarm(long timeInMillis, int requestCode, Intent i, Uri uri) {
           i.setData(uri)
            PendingIntent pi = PendingIntent.getService(MainActivity.context, requestCode, i, PendingIntent.FLAG_UPDATE_CURRENT);
            getAlarmManager().set(AlarmManager.RTC_WAKEUP, timeInMillis, pi);
        }