5

My question is a bit complicated so I am going to describe it briefly what I want to achieve. My application receives messages from GCM without any issue. When application is running and is visible to the user I am not displaying notification in Action Bar, I am displaying this message in dialog alert. I use BroadcastReceiver to achieve this.

The main issue is that, when app gets a few notifications in no time. When main activity is visible to the user, the first notification will be shown in dialog alert. And next will be placed in Action Bar as usual Android notifications. And at this moment user disposes the dialog alert and is going to choose a next notification from Action Bar. At this moment I am using in my CloudService (extends IntentService) intent with flag Intent.FLAG_ACTIVITY_CLEAR_TOP and also PendingIntent.FLAG_UPDATE_CURRENT flag for pendingIntent. PendingIntent is just the contentIntent for my NotificationCompat.Builder.

It works in this way that for each user click on the notification from Action Bar, my activity is refreshing (floats to the lower device edge and then floats from the upper edge with dialog alert with message - I am getting the extras from the intent in onResume method). This action is quite OK. Activity has only one instance in that case - I don't have to break through the few instances of the same activity while I have opened few notifications. But the big problem is that when user chooses any of the notifications in each case the last one will open in dialog alert. Activity seems to has the same intent despite of PendingIntent.FLAG_UPDATE_CURRENT.

There are two methods in CloudService which handle cloud messages:

private void showNotification(Bundle extras) {
    notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);

    String message = extras.getString(CloudMetaData.MESSAGE);

    if (App.isMyActivityVisible() && !CloudMessageDialogFragment.isAttached()) {
        sendBroadcast(message, NOTIFICATION_ID);
    } else {
        Intent intent = new Intent(this, MyParentActivity.class);
        intent.putExtra(CloudMetaData.MESSAGE, message);
        intent.putExtra(CloudMetaData.NOTIFICATION_ID, NOTIFICATION_ID);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setSmallIcon(R.drawable.ic_launcher);
        builder.setContentTitle(getString(R.string.app_name));
        builder.setStyle(new NotificationCompat.BigTextStyle().bigText(alert));
        builder.setContentText(alert);
        builder.setAutoCancel(true);
        builder.setDefaults(Notification.DEFAULT_SOUND);
        builder.setContentIntent(contentIntent);
        notificationManager.notify(NOTIFICATION_ID, builder.build());
    }

    NOTIFICATION_ID++;
}

And method which send broadcast is just like that:

private void sendBroadcast(String message, int notificationId) {
    Intent intent = new Intent();
    intent.setAction(ACTION_FROM_CLOUD_SERVICE);
    intent.putExtra(CloudMetaData.MESSAGE, message);
    intent.putExtra(CloudMetaData.NOTIFICATION_ID, notificationId);
    sendBroadcast(intent);
}

In which way can I achieve similar solution? But it is important for user of course to open notification from Action Bar and shown him its correct message.

EDIT

I have switched my dialog alert into the dialog activity. This is its definition in AndroidManifest:

<activity
    android:name="com.myapp.activity.CloudMessageDialogActivity"
    android:theme="@android:style/Theme.Dialog"
    android:parentActivityName="com.myapp.activity.MyParentActivity"/>

But the result is still the same - when app receives a few notifications, clicking on one of them will open the dialog with the intent for the last received notification.

woyaru
  • 5,544
  • 13
  • 54
  • 92
  • 1
    You can use dialog activity – user2851150 Jul 03 '14 at 10:33
  • @user2851150 in which way? At this moment I cannot refactor too much my application. My main activity is just class extending `Activity`. And in this activity I am showing dialog alert which is just extending `DialogFragment`. – woyaru Jul 03 '14 at 10:41
  • 1
    Its just like creating similar to activity, but in the manifest file u have to change the theme of Activity like this " " – user2851150 Jul 04 '14 at 05:13
  • @user2851150 I have tried with dialog activity but the result is the same - every time I open notification it has the intent with data for the last received notification. So in fact there is no difference between dialog activity and dialog fragment which I used at the beginning. – woyaru Jul 07 '14 at 09:29
  • How ur generating NotificationId ..? – user2851150 Jul 07 '14 at 09:58
  • `NOTIFICATION_ID` is incremented for each new received notification. – woyaru Jul 07 '14 at 10:45
  • PendingIntent pendingIntent = PendingIntent.getActivity( GcmIntentService.this, notificationId, mLaunchActivity, PendingIntent.FLAG_ONE_SHOT); – user2851150 Jul 07 '14 at 10:57
  • From documentation: `Flag indicating that this PendingIntent can be used only once.` And in fact notification opens only once. Next notifications don't open at all. – woyaru Jul 07 '14 at 11:17
  • So you can create different types of notification for same app. – user2851150 Jul 07 '14 at 11:20
  • I need only one type of notification. `FLAG_ONE_SHOT` is not a solution. – woyaru Jul 07 '14 at 11:35
  • 1
    I did not read through the question carefully, but I have guts that you are not using the `PendingIntent` correctly. Pass a unique request code and see what happens; i.e., change the constructor with this: `PendingIntent contentIntent = PendingIntent.getActivity(this, NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);` – ozbek Jul 08 '14 at 06:35
  • 1
    I have explained [**elsewhere@SO**](http://stackoverflow.com/a/19418503/1893766) why you need to use a unique request code in `PendingIntent`s – ozbek Jul 08 '14 at 06:42
  • Yes, it is what I was looking for. Thanks @shoerat. It needs to change `request code` of the `PendingIntent.getActivity()` method. If you post you answer I will accept it and give it bounty. – woyaru Jul 08 '14 at 07:47

1 Answers1

3

But the big problem is that when user chooses any of the notifications in each case the last one will open in dialog alert. Activity seems to has the same intent despite of PendingIntent.FLAG_UPDATE_CURRENT.

That's because you are using the same request code (i.e., 0) for all PendingIntents here:

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent,
        PendingIntent.FLAG_UPDATE_CURRENT);

By doing so, you are ultimately receiving the same intent, because the platform is failing to see the difference between the intents and delivering the same object everytime:

... it is important to know when two Intents are considered to be the same for purposes of retrieving a PendingIntent. A common mistake people make is to create multiple PendingIntent objects with Intents that only vary in their "extra" contents, expecting to get a different PendingIntent each time. This does not happen. The parts of the Intent that are used for matching are the same ones defined by Intent.filterEquals. If you use two Intent objects that are equivalent as per Intent.filterEquals, then you will get the same PendingIntent for both of them.

So, instead of a constant value, please use a unique request code. For e.g. change the above line with:

PendingIntent contentIntent = PendingIntent.getActivity(this, NOTIFICATION_ID,
        intent, PendingIntent.FLAG_UPDATE_CURRENT);

Hope this helps.

ozbek
  • 20,955
  • 5
  • 61
  • 84