Cakeee
Cakeee

Reputation: 49

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

Upvotes: 3

Views: 1363

Answers (2)

Ferdous Ahamed
Ferdous Ahamed

Reputation: 21766

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~

Upvotes: 3

Mehran Zamani
Mehran Zamani

Reputation: 831

This PendingIntent.FLAG_CANCEL_CURRENT is your problem. based on what you want to do use different flag(s) in your code and that works as you expect!

PendingIntent contentIntent = PendingIntent.getActivity(context,
                0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);

for example: FLAG_ACTIVITY_SINGLE_TOP, FLAG_ACTIVITY_CLEAR_TOP, FLAG_ACTIVITY_NEW_TASK, ... or don't use any flag at all (0).

PendingIntent.FLAG_ONE_SHOT forces your program to use pendingintent just once. be careful that calling setAlarm with different putString may not change the result.

EDIT: put this lines in your Schedule.java line 33 and 34. this is going to change notification everytime but it is not a good solution, you should replace "something different" + bigText with different variable string.

String titleText = mPrefs.getString("titleText", "");
String bigText = mPrefs.getString("bigText", "");
SharedPreferences.Editor mPrefsTextsEditor = getSharedPreferences("notifications", 0).edit();
bigText = "something different" + bigText;
titleText = "something different" + titleText;
mPrefsTextsEditor .putString("bigText", bigText).apply();
mPrefsTextsEditor .putString("titleText", titleText).apply();

Upvotes: 0

Related Questions