Merging multiple android notifications.

Chetan Ashtivkar
HopBucket
Published in
3 min readJan 7, 2017

My name is Chetan Ashtivkar, I am a software engineer at HopBucket. HopBucket is a platform which helps you plan the perfect trip. You can use your friend’s ideas or you can take help of other travelers who have been to that particular place.

In our app we use firebase notifications to notify our users about the activities on HopBucket, which includes new likes or comments on their trips, new friend joining HopBucket, featured trips etc. We had already setup all the necessary infrastructure for sending notification from cloud and had implemented the FirebaseMessagingService in our app.

When we push a notification from the cloud it shows up in the notification drawer. Everything is great up to this point. But when the app receives another notification — while the previous notification is still in the notification drawer — it replaces the last notification. This is clearly not desirable.

If there is a single notification in the notification drawer then clicking on it should perform the desired action. On the other hand, if there are multiple notifications, they should simply open the notification center in the HopBucket app where all the past notifications are shown.

I asked this question on stackoverflow, but did not get any answers. So after some brainstorming we came up with a solution.

To achieve the desired behavior, we used SharedPreferences . The SharedPreferences class is used to save key-value pair data. We are using InboxStyle Notifications for merging notifications. There might be better ways to do it and if you come across any of it then please comment down below or post your answers/ suggestions/ queries here

The complete code we wrote is as follows:

public class MyFirebaseMessagingService  extends FirebaseMessagingService {private static final String TAG = "MyFirebaseMsgService";
private static final String actionLiked = "liked";
private static final int NOTIFICATION_ID = 1593;
private final String GROUP_KEY = "GROUP_KEY_RANDOM_NAME";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
ArrayList<String>notificationString= new ArrayList<>();
if (remoteMessage.getData().size() > 0) {Map<String, String> dataFromCloud = remoteMessage.getData();
String action = dataFromCloud.get("action");
String userName = dataFromCloud.get("userName");
switch (action) {
case actionLiked:
notificationString.add(action);
Intent intent = new Intent(this, LikeActivity.class);
String message = userName +" liked your photo.";
sendNotification(message, intent);
break;
default:
break;
}
}
}
@TargetApi(Build.VERSION_CODES.M)
private void sendNotification(String messageBody, Intent intent) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
Intent onCancelNotificationReceiver = new Intent(this, CancelNotificationReceiver.class);
PendingIntent onCancelNotificationReceiverPendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0,
onCancelNotificationReceiver, 0);
String notificationHeader = this.getResources().getString(R.string.app_name);NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
StatusBarNotification[] notifications = manager.getActiveNotifications();
for (int i = 0; i < notifications.length; i++) {
if (notifications[i].getPackageName().equals(getApplicationContext().getPackageName())) {
Log.d("Notification", notifications[i].toString());Intent startNotificationActivity = new Intent(this, NotificationCenterActivity.class);
startNotificationActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, startNotificationActivity,
PendingIntent.FLAG_ONE_SHOT);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentTitle(notificationHeader)
.setContentText("Tap to open")
.setAutoCancel(true)
.setStyle(getStyleForNotification(messageBody))
.setGroupSummary(true)
.setGroup(GROUP_KEY)
.setContentIntent(pendingIntent)
.setDeleteIntent(onCancelNotificationReceiverPendingIntent)
.build();
SharedPreferences sharedPreferences = getSharedPreferences("NotificationData", 0);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(String.valueOf(new Random(NOTIFICATION_ID)), messageBody);
editor.apply();
notificationManager.notify(NOTIFICATION_ID, notification);
return;
}
}
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Notification notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentTitle(notificationHeader)
.setContentText(messageBody)
.setAutoCancel(true)
.setGroup(GROUP_KEY)
.setContentIntent(pendingIntent)
.setDeleteIntent(onCancelNotificationReceiverPendingIntent)
.build();
SharedPreferences sharedPreferences = getSharedPreferences("NotificationData", 0);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(String.valueOf(new Random(NOTIFICATION_ID)), messageBody);
editor.apply();
notificationManager.notify(NOTIFICATION_ID, notificationBuilder);
}
private NotificationCompat.InboxStyle getStyleForNotification(String messageBody) {
NotificationCompat.InboxStyle inbox = new NotificationCompat.InboxStyle();
SharedPreferences sharedPref = getSharedPreferences("NotificationData", 0);
Map<String, String> notificationMessages = (Map<String, String>) sharedPref.getAll();
Map<String, String> myNewHashMap = new HashMap<>();
for (Map.Entry<String, String> entry : notificationMessages.entrySet()) {
myNewHashMap.put(entry.getKey(), entry.getValue());
}
inbox.addLine(messageBody);
for (Map.Entry<String, String> message : myNewHashMap.entrySet()) {
inbox.addLine(message.getValue());
}
inbox.setBigContentTitle(this.getResources().getString(R.string.app_name))
.setSummaryText("Tap to open");
return inbox;
}}

Here you will have to clear the saved shared preferences whenever user clicks on the notification i.e. when the new activity is launched or whenever the user cancels the notification from notification drawer. For that we have created a BroadcastReceiver which clears all the previously saved notification data.

Here is the code.

public class CancelNotificationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPreferences = context.getSharedPreferences("NotificationData", 0);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.clear();
editor.apply();
}
}

Just call it in onCreate of the Activities which can be opened through notification. In our case LikeActivity and NotificationCenterActivity.

This is a working piece of code and there is a lot scope for optimization so please feel free to suggest any edits. Hope this will be helpful to someone.

The HopBucket Android app is available for free on the Play Store. You can visit the website at https://hopbucket.com .

--

--

Chetan Ashtivkar
HopBucket

Logical writer : Write logic for android apps and servers.