Properly group Android push notifications by channel (#5548)

This commit is contained in:
Elias Nahum 2021-07-20 11:36:42 -04:00 committed by GitHub
parent 90cce88358
commit ba78bc9d00
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 31 deletions

View file

@ -1,5 +1,6 @@
package com.mattermost.rnbeta;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.SharedPreferences;
@ -66,11 +67,9 @@ public class CustomPushNotification extends PushNotification {
notificationsInChannel.remove(channelId);
saveNotificationsMap(context, notificationsInChannel);
if (context != null) {
for (final Integer notificationId : notifications) {
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.cancel(notificationId);
}
for (final Integer notificationId : notifications) {
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.cancel(notificationId);
}
}
}
@ -120,23 +119,32 @@ public class CustomPushNotification extends PushNotification {
switch (type) {
case PUSH_TYPE_MESSAGE:
case PUSH_TYPE_SESSION:
boolean createSummary = type.equals(PUSH_TYPE_MESSAGE);
if (!mAppLifecycleFacade.isAppVisible()) {
if (type.equals(PUSH_TYPE_MESSAGE)) {
if (channelId != null) {
Map<String, List<Integer>> notificationsInChannel = loadNotificationsMap(mContext);
synchronized (notificationsInChannel) {
List<Integer> list = notificationsInChannel.get(channelId);
if (list == null) {
list = Collections.synchronizedList(new ArrayList(0));
}
list.add(0, notificationId);
notificationsInChannel.put(channelId, list);
saveNotificationsMap(mContext, notificationsInChannel);
List<Integer> list = notificationsInChannel.get(channelId);
if (list == null) {
list = Collections.synchronizedList(new ArrayList(0));
}
list.add(0, notificationId);
if (list.size() > 1) {
createSummary = false;
}
if (createSummary) {
// Add the summary notification id as well
list.add(0, notificationId + 1);
}
notificationsInChannel.put(channelId, list);
saveNotificationsMap(mContext, notificationsInChannel);
}
}
super.postNotification(notificationId);
buildNotification(notificationId, createSummary);
} else {
notifyReceivedToJS();
}
@ -173,10 +181,25 @@ public class CustomPushNotification extends PushNotification {
}
}
private void buildNotification(Integer notificationId, boolean createSummary) {
final PendingIntent pendingIntent = super.getCTAPendingIntent();
final Notification notification = buildNotification(pendingIntent);
if (createSummary) {
final Notification summary = getNotificationSummaryBuilder(pendingIntent).build();
super.postNotification(summary, notificationId + 1);
}
super.postNotification(notification, notificationId);
}
@Override
protected NotificationCompat.Builder getNotificationBuilder(PendingIntent intent) {
Bundle bundle = mNotificationProps.asBundle();
return CustomPushNotificationHelper.createNotificationBuilder(mContext, intent, bundle);
return CustomPushNotificationHelper.createNotificationBuilder(mContext, intent, bundle, false);
}
protected NotificationCompat.Builder getNotificationSummaryBuilder(PendingIntent intent) {
Bundle bundle = mNotificationProps.asBundle();
return CustomPushNotificationHelper.createNotificationBuilder(mContext, intent, bundle, true);
}
private void notificationReceiptDelivery(String ackId, String postId, String type, boolean isIdLoaded, ResolvePromise promise) {

View file

@ -137,7 +137,7 @@ public class CustomPushNotificationHelper {
.addAction(replyAction);
}
public static NotificationCompat.Builder createNotificationBuilder(Context context, PendingIntent intent, Bundle bundle) {
public static NotificationCompat.Builder createNotificationBuilder(Context context, PendingIntent intent, Bundle bundle, boolean createSummary) {
final NotificationCompat.Builder notification = new NotificationCompat.Builder(context, CHANNEL_HIGH_IMPORTANCE_ID);
String channelId = bundle.getString("channel_id");
@ -148,7 +148,7 @@ public class CustomPushNotificationHelper {
addNotificationExtras(notification, bundle);
setNotificationIcons(context, notification, bundle);
setNotificationMessagingStyle(context, notification, bundle);
setNotificationGroup(notification, channelId);
setNotificationGroup(notification, channelId, createSummary);
setNotificationBadgeType(notification);
setNotificationSound(notification, notificationPreferences);
setNotificationVibrate(notification, notificationPreferences);
@ -373,10 +373,13 @@ public class CustomPushNotificationHelper {
notification.setStyle(messagingStyle);
}
private static void setNotificationGroup(NotificationCompat.Builder notification, String channelId) {
notification
.setGroup(channelId)
.setGroupSummary(true);
private static void setNotificationGroup(NotificationCompat.Builder notification, String channelId, boolean setAsSummary) {
notification.setGroup(channelId);
if (setAsSummary) {
// if this is the first notification for the channel then set as summary, otherwise skip
notification.setGroupSummary(true);
}
}
private static void setNotificationIcons(Context context, NotificationCompat.Builder notification, Bundle bundle) {

View file

@ -4,7 +4,6 @@ import android.content.Context;
import android.content.RestrictionsManager;
import android.os.Bundle;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.io.File;
import java.util.HashMap;
import java.util.List;
@ -101,7 +100,7 @@ private final ReactNativeHost mReactNativeHost =
@Override
protected JSIModulePackage getJSIModulePackage() {
return new CustomMMKVJSIModulePackage();
return (JSIModulePackage) new CustomMMKVJSIModulePackage();
}
};

View file

@ -9,11 +9,13 @@ import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.app.Person;
import java.io.IOException;
import java.util.Objects;
import okhttp3.Call;
import okhttp3.MediaType;
@ -21,7 +23,6 @@ import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.internal.annotations.EverythingIsNonNull;
import org.json.JSONObject;
import org.json.JSONException;
@ -88,21 +89,19 @@ public class NotificationReplyBroadcastReceiver extends BroadcastReceiver {
client.newCall(request).enqueue(new okhttp3.Callback() {
@Override
@EverythingIsNonNull
public void onFailure(Call call, IOException e) {
public void onFailure(@NonNull Call call, @NonNull IOException e) {
Log.i("ReactNative", String.format("Reply FAILED exception %s", e.getMessage()));
onReplyFailed(notificationId);
}
@Override
@EverythingIsNonNull
public void onResponse(Call call, final Response response) throws IOException {
public void onResponse(@NonNull Call call, @NonNull final Response response) throws IOException {
if (response.isSuccessful()) {
onReplySuccess(notificationId, message);
Log.i("ReactNative", "Reply SUCCESS");
} else {
assert response.body() != null;
Log.i("ReactNative", String.format("Reply FAILED status %s BODY %s", response.code(), response.body().string()));
Log.i("ReactNative", String.format("Reply FAILED status %s BODY %s", response.code(), Objects.requireNonNull(response.body()).string()));
onReplyFailed(notificationId);
}
}
@ -133,7 +132,7 @@ public class NotificationReplyBroadcastReceiver extends BroadcastReceiver {
final Intent cta = new Intent(mContext, ProxyService.class);
final PushNotificationProps notificationProps = new PushNotificationProps(bundle);
final PendingIntent pendingIntent = NotificationIntentAdapter.createPendingNotificationIntent(mContext, cta, notificationProps);
NotificationCompat.Builder builder = CustomPushNotificationHelper.createNotificationBuilder(mContext, pendingIntent, bundle);
NotificationCompat.Builder builder = CustomPushNotificationHelper.createNotificationBuilder(mContext, pendingIntent, bundle, false);
Notification notification = builder.build();
NotificationCompat.MessagingStyle messagingStyle = NotificationCompat.MessagingStyle.extractMessagingStyleFromNotification(notification);
assert messagingStyle != null;