Android Multiple Notifications and with multiple intents

14,404

Solution 1

You create multiple intents that are mixed. I cleaned up the code (but did not test it)

    NotificationManager nm = (NotificationManager) ctx
            .getSystemService(Context.NOTIFICATION_SERVICE);

    Resources res = ctx.getResources();

    // Creates an explicit intent for an Activity in your app
    Intent resultIntent = new Intent(this, ResultActivity.class);
    String pass = text.getText().toString();
    resultIntent.setData(new Uri.Builder().scheme("data")
            .appendQueryParameter("text", "my text").build());
    resultIntent.putExtra("title", pass);
    resultIntent.putExtra("uid", i);

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    // Adds the back stack for the Intent (but not the Intent itself)
    stackBuilder.addParentStack(ResultActivity.class);
    // Adds the Intent that starts the Activity to the top of the stack
    stackBuilder.addNextIntent(resultIntent);
    PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
            PendingIntent.FLAG_UPDATE_CURRENT);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
    builder.setSmallIcon(R.drawable.ic_launcher)
            .setLargeIcon(
                    BitmapFactory.decodeResource(res,
                            R.drawable.ic_launcher))
            .setTicker("Remember to " + text.getText())
            .setWhen(System.currentTimeMillis()).setAutoCancel(true)
            .setContentTitle(text.getText())
            .setContentIntent(resultPendingIntent);

    Notification n = builder.build();
    n.flags = Notification.FLAG_NO_CLEAR;
    nm.notify(i++, n);

    text.setText(null);

Solution 2

I know this was a lot time ago but i feel that the answers have not said anything about the problem in your code. So the problem is pretty much here PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);

So you create a pendingIntent from the stackbuilder whith the flag of update_current. If you look at FLAG_UPDATE_CURRENT it says

 /**
 * Flag indicating that if the described PendingIntent already exists,
 * then keep it but replace its extra data with what is in this new
 * Intent. For use with {@link #getActivity}, {@link #getBroadcast}, and
 * {@link #getService}. <p>This can be used if you are creating intents where only the
 * extras change, and don't care that any entities that received your
 * previous PendingIntent will be able to launch it with your new
 * extras even if they are not explicitly given to it.
 */
public static final int FLAG_UPDATE_CURRENT = 1<<27;

So what happens in your use case is that you create two identical pendingintents from the stackbuilder and the second intent overrides the first one . Actually you never create a second you just update the extras of the first one.

So unfortunately there is no available flag for your use case , but there is a good hack around it. What you can do is use the setAction of your resultIntent and place a random string or a string that makes sense to your app.

eg. resultIntent.setAction("dummy_action_" + notification.id);

This will make your resultIntent unique enough , so that the pendingIntent will create it rather than updating a previous one.

Solution 3

Set different requestCode helps me create and update current intent.

val pendingIntent = PendingIntent.getActivity(
  this,
  notificationID,
  intent,
  PendingIntent.FLAG_UPDATE_CURRENT
)
Share:
14,404
EGHDK
Author by

EGHDK

Updated on June 22, 2022

Comments

  • EGHDK
    EGHDK about 2 years

    I have a fairly simple app that takes the input from a user and then sets it as a notification. The user can create as many notifications as he/she likes. I want the user to click the notification and get taken to a new activity called ResultActivity. ResultActivity in turn reads in the putExtras from the notifications intent and shows it to the user. The code below allows me to do almost everything I wanted, except anytime a notification is pressed, I receive the putExtra of the last created notification.

    Intent notificationIntent = new Intent(ctx, MainActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(ctx, i,notificationIntent,PendingIntent.FLAG_CANCEL_CURRENT);
    
    NotificationManager nm = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
    
    Resources res = ctx.getResources();
    NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
    builder.setContentIntent(contentIntent)
        .setSmallIcon(R.drawable.ic_launcher)
        .setLargeIcon(BitmapFactory.decodeResource(res,R.drawable.ic_launcher))
        .setTicker("Remember to " + text.getText())
        .setWhen(System.currentTimeMillis()).setAutoCancel(true)
        .setContentTitle(text.getText());
    
    // Creates an explicit intent for an Activity in your app
    Intent resultIntent = new Intent(this, ResultActivity.class);
    String pass = text.getText().toString();
    
    resultIntent.putExtra("title", pass);
    resultIntent.putExtra("uid", i);
    
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    // Adds the back stack for the Intent (but not the Intent itself)
    stackBuilder.addParentStack(ResultActivity.class);
    // Adds the Intent that starts the Activity to the top of the stack
    stackBuilder.addNextIntent(resultIntent);
    PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
    
    new Uri.Builder().scheme("data").appendQueryParameter("text", "my text").build();
    builder.setContentIntent(resultPendingIntent);
    
    Notification n = builder.build();
    n.flags = Notification.FLAG_NO_CLEAR;
    nm.notify(i++, n);
    text.setText(null);
    
    1. Open the application

    2. Type in "One"

    3. Hit ok

    4. Notification is sent

    5. Open the application

    6. Type in "Two"

    7. Hit ok

    8. Notification is sent

    Now you have two notifications. One that says "One" and one that says "Two". If you click on the notification "Two" it takes you to a screen that says "Two". Perfect!

    If you click on the notification "One" it takes you to a screen that says "Two". BROKEN!

    ResultActivity.java

    public class ResultActivity extends Activity {
        String title = null;
        TextView text;
    
        int i=0;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity);
            text = (TextView) findViewById(R.id.textView1);
    
    
    
            title = getIntent().getStringExtra("title");
             i = getIntent().getIntExtra("uid", 0);
    
    
            text.setText(title);
    
        }
    
    • Cat
      Cat over 11 years
      Please do not repost questions, even if you delete the old one(s).
  • EGHDK
    EGHDK over 11 years
    I would like to do this the "proper" way. I just tried UPDATE_CURRENT, but I get the same problem.
  • EGHDK
    EGHDK over 11 years
    I also tried adding notificationIntent.setAction("ACTION_" + System.nanoTime); but that didn't do the trick either.
  • Tobias Ritzau
    Tobias Ritzau over 11 years
    The proper way is for one app to show one notification (look for "Stack your notifications"). If you have several notifications you should collect them into one. If you need to display multiple notifications anyway they should display different data. Thus, set your data in the data parameter not an extra.
  • Tobias Ritzau
    Tobias Ritzau over 11 years
    Sorry, I mixed it up with your virtually identical questions that where I tried to help you...
  • EGHDK
    EGHDK over 11 years
    Hmmm... so I've been using putExtra when I should be using putData? EDIT: I just noticed theres no such thing as putData. Care to clarify?
  • EGHDK
    EGHDK over 11 years
    Okay, so I see the changes you have made, and your code works (without errors in eclipse), but it still has the same problem as before. Do you think my ResultActivity.java might be the problem? I upvoted your question because I believe you're on the right track. But there must be something that is not causing it to work properly. I also added in my ResultActivity.java in my question
  • Tobias Ritzau
    Tobias Ritzau over 11 years
    Sorry, replace "my text" with pass
  • EGHDK
    EGHDK over 11 years
    IT WORKED! This is awesome and exactly what I've been trying to do for such a long time. I really appreciate the help and your time!
  • EGHDK
    EGHDK over 11 years
    One last thing actually. If I set the two notifications to have the same title the app gets a bit glitchy, as it won't clear the notification in the ResultActivity. Any idea why?
  • Tobias Ritzau
    Tobias Ritzau over 11 years
    The title is more or less the id, add the "ACTION_" + System.currentTimeMillis() fix to the same intent as I set the data, and all intents will be unique. Or even better add a second parameter that you can call time to the intent (resultIntent.setData(new Uri.Builder().scheme("data") .appendQueryParameter("text", "my text")..appendQueryParameter("time", String.valueOf(System.currentTimeMillis()).build());)
  • Mehul Ranpara
    Mehul Ranpara over 7 years
    What if i have to pass arraylist in ResultActivity using resultIntent.setData?
  • Jishant
    Jishant about 7 years
    only using PendingIntent.FLAG_ONE_SHOT worked for me .. is this can create any other issue?
  • Murcielago
    Murcielago over 5 years
    I lost a solid 4 hours to this. resultIntent.setAction solved it for me. Thanks!
  • Bhaumik Ghodasara
    Bhaumik Ghodasara over 4 years
    I don't know why people are not voting this answer up. If you use same request code than it will create only one pending intent and it will update every next time when you use same request code to create another one. I have tried this solution and it's working like a charm. Thanks buddy :)
  • Akhilesh Mani
    Akhilesh Mani about 4 years
    Correct answer. Thanks
  • Mairyu
    Mairyu about 4 years
    I lost more than 4 hours on that, I had no idea that was the issue I had all along, thanks so much for this WA!!!
  • saschoar
    saschoar almost 3 years
    When targeting API 29+, using intent.setIdentifier() would be cleaner: developer.android.com/reference/android/content/…
  • DocAsh59
    DocAsh59 about 2 years
    This now seems to be working for me. Thanks for the tip!