Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display Android notifications as a dialog alerts when App is running and visible

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.

like image 239
woyaru Avatar asked Oct 21 '22 05:10

woyaru


1 Answers

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.

like image 83
ozbek Avatar answered Oct 23 '22 03:10

ozbek