Search code examples
androidnotificationsalarmmanager

Android: AlarmManager shows same notifications all the time


I create multiple notifications with different text. However, AlarmManager always shows notification with same text, replacing old notification if the previous one not swiped away. NOTIFY_ID is always different (debugged). Also I've found out that if I crash app in onRecieve method after showing notification it works fine... Here is the code:

public class Schedule extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
        wakeLock.acquire();

        //next is notification code. //

        //get res.
        SharedPreferences mPrefs = context.getSharedPreferences("appsettings", 0);

        String titleText = mPrefs.getString("titleText", "");
        String bigText = mPrefs.getString("bigText", "");
        int NOTIFY_ID = mPrefs.getInt("id", 0);

        //create intent.
        Intent notificationIntent = new Intent(context, MainActivity.class);
        PendingIntent contentIntent = PendingIntent.getActivity(context,
                0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);

        //get res.
        Resources res = context.getResources();

        //build notification.
        Notification.Builder builder = new Notification.Builder(context)
                .setContentIntent(contentIntent)
                .setSmallIcon(R.drawable.statusbaricon)
                .setAutoCancel(true)
                .setContentTitle(titleText)
                .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
                .setContentText(bigText);


        //check vibration.
        if (mPrefs.getBoolean("vibration", true)) {
            builder.setVibrate(new long[] { 0, 50 });
        }

        //create default title if empty.
        if (titleText.length() == 0) {
            builder.setContentTitle(context.getString(R.string.notification_Title_Default));
        }

        //show notification. check for delay.
        builder.setWhen(System.currentTimeMillis());

        Notification notification = new Notification.BigTextStyle(builder)
                .bigText(bigText).build();

        NotificationManager notificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(NOTIFY_ID, notification);

        ////
        wakeLock.release();
    }

    public void setAlarm(Context context) {

        SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
        int delay = mPrefs.getInt("delay", 0);
        int id = mPrefs.getInt("id", 0);

        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(context, Schedule.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_ONE_SHOT);
        alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() /* + 1000 * 60 * delay */, pendingIntent);
    }
}

And this is how I call it:

    //store stuff to revoke in Schedule.
    mPrefsEditor.putString("bigText", bigText).apply();
    mPrefsEditor.putString("titleText", titleText).apply();

    Schedule schedule = new Schedule();
    schedule.setAlarm(context);

Solution

  • Use different requestCode for different PendingIntent with flag FLAG_UPDATE_CURRENT.

    PendingIntent contentIntent = PendingIntent.getActivity(context, requestCode, 
                                  notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    

    1. From setAlarm() method send notification id, titleText and bigText to broadcast receiver through intent and also use flag FLAG_UPDATE_CURRENT instead of FLAG_ONE_SHOT.

    Update setAlarm() method as below:

    public void setAlarm(Context context) {
    
        SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
        int delay = mPrefs.getInt("delay", 0);
        int id = mPrefs.getInt("id", 0);
        String titleText = mPrefs.getString("titleText", "");
        String bigText = mPrefs.getString("bigText", "");
    
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    
        // send notification id, titleText and bigText with intent 
        // to use later when alarm triggers
        Intent intent = new Intent(context, Schedule.class);
        intent.putExtra("NOTIFICATION_ID", id);
        intent.putExtra("TITLE_TEXT", titleText);
        intent.putExtra("BIG_TEXT", bigText);
    
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() /* + 1000 * 60 * delay */, pendingIntent);
    }
    

    2. In your onReceive() method, get notification id, titleText and bigText from Intent.

    3. Use notification id as requestCode for contentIntent and use titleText and bigText for notification text.

    Update onReceive() method as below:

    public class Schedule extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
            PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
            PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
            wakeLock.acquire();
    
            // get id, titleText and bigText from intent
            int NOTIFY_ID = intent.getIntExtra("NOTIFICATION_ID", 0);
            String titleText = intent.getStringExtra("TITLE_TEXT");
            String bigText = intent.getStringExtra("BIG_TEXT");
    
            // Create intent.
            Intent notificationIntent = new Intent(context, MainActivity.class);
    
            // use NOTIFY_ID as requestCode
            PendingIntent contentIntent = PendingIntent.getActivity(context,
                    NOTIFY_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    
            // get res.
            Resources res = context.getResources();
    
            // build notification.
            Notification.Builder builder = new Notification.Builder(context)
                    .setContentIntent(contentIntent)
                    .setSmallIcon(R.drawable.statusbaricon)
                    .setAutoCancel(true)
                    .setContentTitle(titleText)
                    .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
                    .setContentText(bigText);
    
    
            // check vibration.
            if (mPrefs.getBoolean("vibration", true)) {
                builder.setVibrate(new long[] { 0, 50 });
            }
    
            // create default title if empty.
            if (titleText.length() == 0) {
                builder.setContentTitle(context.getString(R.string.notification_Title_Default));
            }
    
            // show notification. check for delay.
            builder.setWhen(System.currentTimeMillis());
    
            Notification notification = new Notification.BigTextStyle(builder)
                    .bigText(bigText).build();
    
            NotificationManager notificationManager = (NotificationManager) context
                    .getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.notify(NOTIFY_ID, notification);
    
            ////
            wakeLock.release();
        }
    
        ....................
        .......................... 
    }
    

    Hope this will help~