[Gekidou] Update dependencies (#5581)

* Update detox deps

* Push notifications (android & launcher)

* Update dependencies
This commit is contained in:
Elias Nahum
2021-08-01 21:09:19 -04:00
committed by GitHub
parent c452ef8038
commit 8d2bd32897
28 changed files with 7553 additions and 6161 deletions

View File

@@ -1,5 +1,7 @@
package com.mattermost.helpers;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.WritableMap;
@@ -20,4 +22,27 @@ public class Credentials {
keychainModule.getGenericPasswordForOptions(options, promise);
}
public static String getCredentialsForServerSync(ReactApplicationContext context, String serverUrl) {
final String[] token = new String[1];
Credentials.getCredentialsForServer(context, serverUrl, new ResolvePromise() {
@Override
public void resolve(@Nullable Object value) {
WritableMap map = (WritableMap) value;
if (map != null) {
token[0] = map.getString("password");
String service = map.getString("service");
assert service != null;
if (service.isEmpty()) {
String[] credentials = token[0].split(",[ ]*");
if (credentials.length == 2) {
token[0] = credentials[0];
}
}
}
}
});
return token[0];
}
}

View File

@@ -0,0 +1,461 @@
package com.mattermost.helpers;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.app.Person;
import androidx.core.app.RemoteInput;
import androidx.core.graphics.drawable.IconCompat;
import com.facebook.react.bridge.ReactApplicationContext;
import com.mattermost.rnbeta.NotificationDismissService;
import com.mattermost.rnbeta.NotificationPreferences;
import com.mattermost.rnbeta.NotificationReplyBroadcastReceiver;
import com.mattermost.rnbeta.R;
import com.wix.reactnativenotifications.core.NotificationIntentAdapter;
import com.wix.reactnativenotifications.core.notification.PushNotificationProps;
import java.io.IOException;
import java.util.Date;
import java.util.Objects;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class CustomPushNotificationHelper {
public static final String CHANNEL_HIGH_IMPORTANCE_ID = "channel_01";
public static final String CHANNEL_MIN_IMPORTANCE_ID = "channel_02";
public static final String KEY_TEXT_REPLY = "CAN_REPLY";
public static final int MESSAGE_NOTIFICATION_ID = 435345;
public static final String NOTIFICATION_ID = "notificationId";
public static final String NOTIFICATION = "notification";
private static NotificationChannel mHighImportanceChannel;
private static NotificationChannel mMinImportanceChannel;
private static void addMessagingStyleMessages(Context context, NotificationCompat.MessagingStyle messagingStyle, String conversationTitle, Bundle bundle) {
String message = bundle.getString("message", bundle.getString("body"));
String senderId = bundle.getString("sender_id");
String serverUrl = bundle.getString("server_url");
if (senderId == null) {
senderId = "sender_id";
}
Bundle userInfoBundle = bundle.getBundle("userInfo");
String senderName = getSenderName(bundle);
if (userInfoBundle != null) {
boolean localPushNotificationTest = userInfoBundle.getBoolean("test");
if (localPushNotificationTest) {
senderName = "Test";
}
}
if (conversationTitle == null || !android.text.TextUtils.isEmpty(senderName.trim())) {
message = removeSenderNameFromMessage(message, senderName);
}
long timestamp = new Date().getTime();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
messagingStyle.addMessage(message, timestamp, senderName);
} else {
Person.Builder sender = new Person.Builder()
.setKey(senderId)
.setName(senderName);
if (serverUrl != null) {
try {
sender.setIcon(IconCompat.createWithBitmap(Objects.requireNonNull(userAvatar(context, serverUrl, senderId))));
} catch (IOException e) {
e.printStackTrace();
}
}
// if (serverUrl == null) {
message = "Unknown Server\n" + message;
// }
messagingStyle.addMessage(message, timestamp, sender.build());
}
}
private static void addNotificationExtras(NotificationCompat.Builder notification, Bundle bundle) {
Bundle userInfoBundle = bundle.getBundle("userInfo");
if (userInfoBundle == null) {
userInfoBundle = new Bundle();
}
String channelId = bundle.getString("channel_id");
if (channelId != null) {
userInfoBundle.putString("channel_id", channelId);
}
notification.addExtras(userInfoBundle);
}
private static void addNotificationReplyAction(Context context, NotificationCompat.Builder notification, Bundle bundle, int notificationId) {
String postId = bundle.getString("post_id");
String serverUrl = bundle.getString("server_url");
if (android.text.TextUtils.isEmpty(postId) || serverUrl == null) {
return;
}
Intent replyIntent = new Intent(context, NotificationReplyBroadcastReceiver.class);
replyIntent.setAction(KEY_TEXT_REPLY);
replyIntent.putExtra(NOTIFICATION_ID, notificationId);
replyIntent.putExtra(NOTIFICATION, bundle);
PendingIntent replyPendingIntent = PendingIntent.getBroadcast(
context,
notificationId,
replyIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
.setLabel("Reply")
.build();
int icon = R.drawable.ic_notif_action_reply;
CharSequence title = "Reply";
NotificationCompat.Action replyAction = new NotificationCompat.Action.Builder(icon, title, replyPendingIntent)
.addRemoteInput(remoteInput)
.setAllowGeneratedReplies(true)
.build();
notification
.setShowWhen(true)
.addAction(replyAction);
}
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");
String postId = bundle.getString("post_id");
int notificationId = postId != null ? postId.hashCode() : MESSAGE_NOTIFICATION_ID;
NotificationPreferences notificationPreferences = NotificationPreferences.getInstance(context);
addNotificationExtras(notification, bundle);
setNotificationIcons(context, notification, bundle);
setNotificationMessagingStyle(context, notification, bundle);
setNotificationGroup(notification, channelId, createSummary);
setNotificationBadgeType(notification);
setNotificationSound(notification, notificationPreferences);
setNotificationVibrate(notification, notificationPreferences);
setNotificationBlink(notification, notificationPreferences);
setNotificationChannel(notification, bundle);
setNotificationDeleteIntent(context, notification, bundle, notificationId);
addNotificationReplyAction(context, notification, bundle, notificationId);
notification
.setContentIntent(intent)
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
.setPriority(Notification.PRIORITY_HIGH)
.setCategory(Notification.CATEGORY_MESSAGE)
.setAutoCancel(true);
return notification;
}
public static void createNotificationChannels(Context context) {
// Notification channels are not supported in Android Nougat and below
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
}
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
if (mHighImportanceChannel == null) {
mHighImportanceChannel = new NotificationChannel(CHANNEL_HIGH_IMPORTANCE_ID, "High Importance", NotificationManager.IMPORTANCE_HIGH);
mHighImportanceChannel.setShowBadge(true);
notificationManager.createNotificationChannel(mHighImportanceChannel);
}
if (mMinImportanceChannel == null) {
mMinImportanceChannel = new NotificationChannel(CHANNEL_MIN_IMPORTANCE_ID, "Min Importance", NotificationManager.IMPORTANCE_MIN);
mMinImportanceChannel.setShowBadge(true);
notificationManager.createNotificationChannel(mMinImportanceChannel);
}
}
private static Bitmap getCircleBitmap(Bitmap bitmap) {
final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(output);
final int color = Color.RED;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawOval(rectF, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
bitmap.recycle();
return output;
}
private static String getConversationTitle(Bundle bundle) {
String title = bundle.getString("channel_name");
if (android.text.TextUtils.isEmpty(title)) {
title = bundle.getString("sender_name");
}
return title;
}
private static int getIconResourceId(Context context, String iconName) {
final Resources res = context.getResources();
String packageName = context.getPackageName();
String defType = "mipmap";
return res.getIdentifier(iconName, defType, packageName);
}
private static NotificationCompat.MessagingStyle getMessagingStyle(Context context, Bundle bundle) {
NotificationCompat.MessagingStyle messagingStyle;
String senderId = "me";
final String serverUrl = bundle.getString("server_url");
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
messagingStyle = new NotificationCompat.MessagingStyle("Me");
} else {
Person.Builder sender = new Person.Builder()
.setKey(senderId)
.setName("Me");
if (serverUrl != null) {
try {
sender.setIcon(IconCompat.createWithBitmap(Objects.requireNonNull(userAvatar(context, serverUrl, "me"))));
} catch (IOException e) {
e.printStackTrace();
}
}
messagingStyle = new NotificationCompat.MessagingStyle(sender.build());
}
String conversationTitle = getConversationTitle(bundle);
setMessagingStyleConversationTitle(messagingStyle, conversationTitle, bundle);
addMessagingStyleMessages(context, messagingStyle, conversationTitle, bundle);
return messagingStyle;
}
private static String getSenderName(Bundle bundle) {
String senderName = bundle.getString("sender_name");
if (senderName != null) {
return senderName;
}
String channelName = bundle.getString("channel_name");
if (channelName != null && channelName.startsWith("@")) {
return channelName;
}
String message = bundle.getString("message");
if (message != null) {
String name = message.split(":")[0];
if (!name.equals(message)) {
return name;
}
}
return getConversationTitle(bundle);
}
public static int getSmallIconResourceId(Context context, String iconName) {
if (iconName == null) {
iconName = "ic_notification";
}
int resourceId = getIconResourceId(context, iconName);
if (resourceId == 0) {
iconName = "ic_launcher";
resourceId = getIconResourceId(context, iconName);
if (resourceId == 0) {
resourceId = android.R.drawable.ic_dialog_info;
}
}
return resourceId;
}
private static String removeSenderNameFromMessage(String message, String senderName) {
int index = message.indexOf(senderName);
if (index == 0) {
message = message.substring(senderName.length());
}
return message.replaceFirst(": ", "").trim();
}
private static void setMessagingStyleConversationTitle(NotificationCompat.MessagingStyle messagingStyle, String conversationTitle, Bundle bundle) {
String channelName = getConversationTitle(bundle);
String senderName = bundle.getString("sender_name");
if (TextUtils.isEmpty(senderName)) {
senderName = getSenderName(bundle);
}
if (conversationTitle != null && !channelName.equals(senderName)) {
messagingStyle.setConversationTitle(conversationTitle);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
messagingStyle.setGroupConversation(true);
}
}
}
private static void setNotificationBadgeType(NotificationCompat.Builder notification) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notification.setBadgeIconType(NotificationCompat.BADGE_ICON_LARGE);
}
}
private static void setNotificationBlink(NotificationCompat.Builder notification, NotificationPreferences notificationPreferences) {
boolean blink = notificationPreferences.getShouldBlink();
if (blink) {
notification.setLights(Color.CYAN, 500, 500);
}
}
private static void setNotificationChannel(NotificationCompat.Builder notification, Bundle bundle) {
// If Android Oreo or above we need to register a channel
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
}
NotificationChannel notificationChannel = mHighImportanceChannel;
boolean testNotification = false;
boolean localNotification = false;
Bundle userInfoBundle = bundle.getBundle("userInfo");
if (userInfoBundle != null) {
testNotification = userInfoBundle.getBoolean("test");
localNotification = userInfoBundle.getBoolean("local");
}
if (testNotification || localNotification) {
notificationChannel = mMinImportanceChannel;
}
notification.setChannelId(notificationChannel.getId());
}
private static void setNotificationDeleteIntent(Context context, NotificationCompat.Builder notification, Bundle bundle, int notificationId) {
// Let's add a delete intent when the notification is dismissed
Intent delIntent = new Intent(context, NotificationDismissService.class);
PushNotificationProps notificationProps = new PushNotificationProps(bundle);
delIntent.putExtra(NOTIFICATION_ID, notificationId);
PendingIntent deleteIntent = NotificationIntentAdapter.createPendingNotificationIntent(context, delIntent, notificationProps);
notification.setDeleteIntent(deleteIntent);
}
private static void setNotificationMessagingStyle(Context context, NotificationCompat.Builder notification, Bundle bundle) {
NotificationCompat.MessagingStyle messagingStyle = getMessagingStyle(context, bundle);
notification.setStyle(messagingStyle);
}
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) {
String smallIcon = bundle.getString("smallIcon");
String channelName = getConversationTitle(bundle);
String senderName = bundle.getString("sender_name");
String serverUrl = bundle.getString("server_url");
int smallIconResId = getSmallIconResourceId(context, smallIcon);
notification.setSmallIcon(smallIconResId);
if (serverUrl != null && channelName.equals(senderName)) {
try {
String senderId = bundle.getString("sender_id");
notification.setLargeIcon(userAvatar(context, serverUrl, senderId));
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void setNotificationSound(NotificationCompat.Builder notification, NotificationPreferences notificationPreferences) {
String soundUri = notificationPreferences.getNotificationSound();
if (soundUri != null) {
if (!soundUri.equals("none")) {
notification.setSound(Uri.parse(soundUri));
}
} else {
Uri defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI;
notification.setSound(defaultUri);
}
}
private static void setNotificationVibrate(NotificationCompat.Builder notification, NotificationPreferences notificationPreferences) {
boolean vibrate = notificationPreferences.getShouldVibrate();
if (vibrate) {
// Use the system default for vibration
notification.setDefaults(Notification.DEFAULT_VIBRATE);
}
}
private static Bitmap userAvatar(Context context, final String serverUrl, final String userId) throws IOException {
final ReactApplicationContext reactApplicationContext = new ReactApplicationContext(context);
final String token = Credentials.getCredentialsForServerSync(reactApplicationContext, serverUrl);
final OkHttpClient client = new OkHttpClient();
final String url = String.format("%s/api/v4/users/%s/image", serverUrl, userId);
Request request = new Request.Builder()
.header("Authorization", String.format("Bearer %s", token))
.url(url)
.build();
Response response = client.newCall(request).execute();
if (response.code() == 200) {
assert response.body() != null;
byte[] bytes = Objects.requireNonNull(response.body()).bytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Log.i("ReactNative", String.format("Fetch profile %s", url));
return getCircleBitmap(bitmap);
}
return null;
}
}

View File

@@ -1,114 +1,109 @@
package com.mattermost.rnbeta;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Person;
import android.app.RemoteInput;
import android.content.Intent;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.media.AudioManager;
import android.net.Uri;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Build;
import android.provider.Settings.System;
import androidx.annotation.Nullable;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.mattermost.helpers.CustomPushNotificationHelper;
import com.mattermost.helpers.DatabaseHelper;
import com.mattermost.helpers.ResolvePromise;
import com.wix.reactnativenotifications.core.notification.PushNotification;
import com.wix.reactnativenotifications.core.NotificationIntentAdapter;
import com.wix.reactnativenotifications.core.ProxyService;
import com.wix.reactnativenotifications.core.notification.PushNotification;
import com.wix.reactnativenotifications.core.AppLaunchHelper;
import com.wix.reactnativenotifications.core.AppLifecycleFacade;
import com.wix.reactnativenotifications.core.JsIOHelper;
import static com.wix.reactnativenotifications.Defs.NOTIFICATION_RECEIVED_EVENT_NAME;
public class CustomPushNotification extends PushNotification {
public static final int MESSAGE_NOTIFICATION_ID = 435345;
public static final String GROUP_KEY_MESSAGES = "mm_group_key_messages";
public static final String NOTIFICATION = "notification";
public static final String NOTIFICATION_ID = "notificationId";
public static final String KEY_TEXT_REPLY = "CAN_REPLY";
public static final String NOTIFICATION_REPLIED_EVENT_NAME = "notificationReplied";
import org.json.JSONArray;
import org.json.JSONObject;
public class CustomPushNotification extends PushNotification {
private static final String PUSH_NOTIFICATIONS = "PUSH_NOTIFICATIONS";
private static final String PUSH_TYPE_MESSAGE = "message";
private static final String PUSH_TYPE_CLEAR = "clear";
private static final String PUSH_TYPE_SESSION = "session";
private static final String PUSH_TYPE_UPDATE_BADGE = "update_badge";
private NotificationChannel mHighImportanceChannel;
private NotificationChannel mMinImportanceChannel;
private static Map<String, Integer> channelIdToNotificationCount = new HashMap<String, Integer>();
private static Map<String, List<Bundle>> channelIdToNotification = new HashMap<String, List<Bundle>>();
private static AppLifecycleFacade lifecycleFacade;
private static Context context;
private static int badgeCount = 0;
private static final String NOTIFICATIONS_IN_CHANNEL = "notificationsInChannel";
public CustomPushNotification(Context context, Bundle bundle, AppLifecycleFacade appLifecycleFacade, AppLaunchHelper appLaunchHelper, JsIOHelper jsIoHelper) {
super(context, bundle, appLifecycleFacade, appLaunchHelper, jsIoHelper);
this.context = context;
createNotificationChannels();
CustomPushNotificationHelper.createNotificationChannels(context);
}
public static void clearNotification(Context mContext, int notificationId, String channelId) {
if (notificationId != -1) {
Integer count = channelIdToNotificationCount.get(channelId);
if (count == null) {
count = -1;
public static void cancelNotification(Context context, String channelId, Integer notificationId) {
if (!android.text.TextUtils.isEmpty(channelId)) {
Map<String, List<Integer>> notificationsInChannel = loadNotificationsMap(context);
List<Integer> notifications = notificationsInChannel.get(channelId);
if (notifications == null) {
return;
}
channelIdToNotificationCount.remove(channelId);
channelIdToNotification.remove(channelId);
notifications.remove(notificationId);
saveNotificationsMap(context, notificationsInChannel);
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.cancel(notificationId);
}
}
if (mContext != null) {
final NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
public static void clearChannelNotifications(Context context, String channelId) {
if (!android.text.TextUtils.isEmpty(channelId)) {
Map<String, List<Integer>> notificationsInChannel = loadNotificationsMap(context);
List<Integer> notifications = notificationsInChannel.get(channelId);
if (notifications == null) {
return;
}
notificationsInChannel.remove(channelId);
saveNotificationsMap(context, notificationsInChannel);
for (final Integer notificationId : notifications) {
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.cancel(notificationId);
if (count != -1) {
int total = CustomPushNotification.badgeCount - count;
int badgeCount = total < 0 ? 0 : total;
CustomPushNotification.badgeCount = badgeCount;
}
}
}
}
public static void clearAllNotifications(Context mContext) {
channelIdToNotificationCount.clear();
channelIdToNotification.clear();
if (mContext != null) {
final NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
public static void clearAllNotifications(Context context) {
if (context != null) {
Map<String, List<Integer>> notificationsInChannel = loadNotificationsMap(context);
notificationsInChannel.clear();
saveNotificationsMap(context, notificationsInChannel);
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.cancelAll();
}
}
@Override
public void onReceived() throws InvalidNotificationException {
public void onReceived() {
final Bundle initialData = mNotificationProps.asBundle();
final String type = initialData.getString("type");
final String ackId = initialData.getString("ack_id");
final String postId = initialData.getString("post_id");
final String channelId = initialData.getString("channel_id");
final boolean isIdLoaded = initialData.getString("id_loaded") != null ? initialData.getString("id_loaded").equals("true") : false;
int notificationId = MESSAGE_NOTIFICATION_ID;
final boolean isIdLoaded = initialData.getString("id_loaded") != null && initialData.getString("id_loaded").equals("true");
int notificationId = CustomPushNotificationHelper.MESSAGE_NOTIFICATION_ID;
if (postId != null) {
notificationId = postId.hashCode();
} else if (channelId != null) {
notificationId = channelId.hashCode();
}
String serverUrl = initialData.getString("server_url", DatabaseHelper.getOnlyServerUrl(context));
String serverUrl = addServerUrlToBundle(initialData);
if (ackId != null && serverUrl != null) {
notificationReceiptDelivery(ackId, serverUrl, postId, type, isIdLoaded, new ResolvePromise() {
@@ -116,7 +111,7 @@ public class CustomPushNotification extends PushNotification {
public void resolve(@Nullable Object value) {
if (isIdLoaded) {
Bundle response = (Bundle) value;
mNotificationProps = createProps(response);
addServerUrlToBundle(response);
}
}
@@ -127,54 +122,42 @@ public class CustomPushNotification extends PushNotification {
});
}
// notificationReceiptDelivery can override mNotificationProps
// so we fetch the bundle again
final Bundle data = mNotificationProps.asBundle();
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);
List<Integer> list = notificationsInChannel.get(channelId);
if (list == null) {
list = Collections.synchronizedList(new ArrayList(0));
}
if (serverUrl == null) {
String message = data.getString("message");
data.putString("message", "Unknown Server\n" + message);
}
list.add(0, notificationId);
if (list.size() > 1) {
createSummary = false;
}
if (channelId != null) {
notificationId = channelId.hashCode();
if (createSummary) {
// Add the summary notification id as well
list.add(0, notificationId + 1);
}
synchronized (channelIdToNotificationCount) {
Integer count = channelIdToNotificationCount.get(channelId);
if (count == null) {
count = 0;
notificationsInChannel.put(channelId, list);
saveNotificationsMap(mContext, notificationsInChannel);
}
}
buildNotification(notificationId, createSummary);
} else {
notifyReceivedToJS();
}
count += 1;
channelIdToNotificationCount.put(channelId, count);
}
synchronized (channelIdToNotification) {
List<Bundle> list = channelIdToNotification.get(channelId);
if (list == null) {
list = Collections.synchronizedList(new ArrayList(0));
}
if (PUSH_TYPE_MESSAGE.equals(type)) {
String senderName = getSenderName(data);
data.putLong("time", new Date().getTime());
data.putString("sender_name", senderName);
data.putString("sender_id", data.getString("sender_id"));
}
list.add(0, data);
channelIdToNotification.put(channelId, list);
}
}
switch(type) {
case PUSH_TYPE_MESSAGE:
case PUSH_TYPE_SESSION:
super.postNotification(notificationId);
break;
case PUSH_TYPE_CLEAR:
cancelNotification(data, notificationId);
break;
break;
case PUSH_TYPE_CLEAR:
clearChannelNotifications(mContext, channelId);
break;
}
if (mAppLifecycleFacade.isReactInitialized()) {
@@ -184,392 +167,102 @@ public class CustomPushNotification extends PushNotification {
@Override
public void onOpened() {
digestNotification();
Bundle data = mNotificationProps.asBundle();
final String channelId = data.getString("channel_id");
if (channelId != null) {
channelIdToNotificationCount.remove(channelId);
channelIdToNotification.remove(channelId);
final String postId = data.getString("post_id");
Integer notificationId = CustomPushNotificationHelper.MESSAGE_NOTIFICATION_ID;
if (postId != null) {
notificationId = postId.hashCode();
}
digestNotification();
if (channelId != null) {
Map<String, List<Integer>> notificationsInChannel = loadNotificationsMap(mContext);
List<Integer> notifications = notificationsInChannel.get(channelId);
notifications.remove(notificationId);
saveNotificationsMap(mContext, notificationsInChannel);
clearChannelNotifications(mContext, channelId);
}
}
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 Notification.Builder getNotificationBuilder(PendingIntent intent) {
// First, get a builder initialized with defaults from the core class.
final Notification.Builder notification = new Notification.Builder(mContext);
protected NotificationCompat.Builder getNotificationBuilder(PendingIntent intent) {
Bundle bundle = mNotificationProps.asBundle();
addNotificationExtras(notification, bundle);
setNotificationIcons(notification, bundle);
setNotificationMessagingStyle(notification, bundle);
setNotificationChannel(notification, bundle);
setNotificationBadgeIconType(notification);
NotificationPreferences notificationPreferences = NotificationPreferences.getInstance(mContext);
setNotificationSound(notification, notificationPreferences);
setNotificationVibrate(notification, notificationPreferences);
setNotificationBlink(notification, notificationPreferences);
String channelId = bundle.getString("channel_id");
int notificationId = channelId != null ? channelId.hashCode() : MESSAGE_NOTIFICATION_ID;
setNotificationNumber(notification, channelId);
setNotificationDeleteIntent(notification, notificationId);
addNotificationReplyAction(notification, notificationId, bundle);
notification
.setContentIntent(intent)
.setVisibility(Notification.VISIBILITY_PRIVATE)
.setPriority(Notification.PRIORITY_HIGH)
.setAutoCancel(true);
return notification;
return CustomPushNotificationHelper.createNotificationBuilder(mContext, intent, bundle, false);
}
private void addNotificationExtras(Notification.Builder notification, Bundle bundle) {
Bundle userInfoBundle = bundle.getBundle("userInfo");
if (userInfoBundle == null) {
userInfoBundle = new Bundle();
}
String channelId = bundle.getString("channel_id");
if (channelId != null) {
userInfoBundle.putString("channel_id", channelId);
}
notification.addExtras(userInfoBundle);
protected NotificationCompat.Builder getNotificationSummaryBuilder(PendingIntent intent) {
Bundle bundle = mNotificationProps.asBundle();
return CustomPushNotificationHelper.createNotificationBuilder(mContext, intent, bundle, true);
}
private void setNotificationIcons(Notification.Builder notification, Bundle bundle) {
String smallIcon = bundle.getString("smallIcon");
String largeIcon = bundle.getString("largeIcon");
int smallIconResId = getSmallIconResourceId(smallIcon);
notification.setSmallIcon(smallIconResId);
int largeIconResId = getLargeIconResourceId(largeIcon);
final Resources res = mContext.getResources();
Bitmap largeIconBitmap = BitmapFactory.decodeResource(res, largeIconResId);
if (largeIconResId != 0 && (largeIconBitmap != null || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)) {
notification.setLargeIcon(largeIconBitmap);
}
}
private int getSmallIconResourceId(String iconName) {
if (iconName == null) {
iconName = "ic_notification";
}
int resourceId = getIconResourceId(iconName);
if (resourceId == 0) {
iconName = "ic_launcher";
resourceId = getIconResourceId(iconName);
if (resourceId == 0) {
resourceId = android.R.drawable.ic_dialog_info;
}
}
return resourceId;
}
private int getLargeIconResourceId(String iconName) {
if (iconName == null) {
iconName = "ic_launcher";
}
return getIconResourceId(iconName);
}
private int getIconResourceId(String iconName) {
final Resources res = mContext.getResources();
String packageName = mContext.getPackageName();
String defType = "mipmap";
return res.getIdentifier(iconName, defType, packageName);
}
private void setNotificationNumber(Notification.Builder notification, String channelId) {
Integer number = channelIdToNotificationCount.get(channelId);
if (number == null) {
number = 0;
}
notification.setNumber(number);
}
private void setNotificationMessagingStyle(Notification.Builder notification, Bundle bundle) {
Notification.MessagingStyle messagingStyle = getMessagingStyle(bundle);
notification.setStyle(messagingStyle);
}
private Notification.MessagingStyle getMessagingStyle(Bundle bundle) {
Notification.MessagingStyle messagingStyle;
String senderId = bundle.getString("sender_id");
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P || senderId == null) {
messagingStyle = new Notification.MessagingStyle("");
} else {
Person sender = new Person.Builder()
.setKey(senderId)
.setName("")
.build();
messagingStyle = new Notification.MessagingStyle(sender);
}
String conversationTitle = getConversationTitle(bundle);
setMessagingStyleConversationTitle(messagingStyle, conversationTitle, bundle);
addMessagingStyleMessages(messagingStyle, conversationTitle, bundle);
return messagingStyle;
}
private String getConversationTitle(Bundle bundle) {
String title = null;
String version = bundle.getString("version");
if (version != null && version.equals("v2")) {
title = bundle.getString("channel_name");
} else {
title = bundle.getString("title");
}
if (android.text.TextUtils.isEmpty(title)) {
ApplicationInfo appInfo = mContext.getApplicationInfo();
title = mContext.getPackageManager().getApplicationLabel(appInfo).toString();
}
return title;
}
private void setMessagingStyleConversationTitle(Notification.MessagingStyle messagingStyle, String conversationTitle, Bundle bundle) {
String channelName = getConversationTitle(bundle);
String senderName = bundle.getString("sender_name");
if (android.text.TextUtils.isEmpty(senderName)) {
senderName = getSenderName(bundle);
}
if (conversationTitle != null && (!conversationTitle.startsWith("@") || channelName != senderName)) {
messagingStyle.setConversationTitle(conversationTitle);
}
}
private void addMessagingStyleMessages(Notification.MessagingStyle messagingStyle, String conversationTitle, Bundle bundle) {
List<Bundle> bundleList;
String channelId = bundle.getString("channel_id");
List<Bundle> bundleArray = channelIdToNotification.get(channelId);
if (bundleArray != null) {
bundleList = new ArrayList<Bundle>(bundleArray);
} else {
bundleList = new ArrayList<Bundle>();
bundleList.add(bundle);
}
int bundleCount = bundleList.size() - 1;
for (int i = bundleCount; i >= 0; i--) {
Bundle data = bundleList.get(i);
String message = data.getString("message", data.getString("body"));
String senderId = data.getString("sender_id");
if (senderId == null) {
senderId = "sender_id";
}
Bundle userInfoBundle = data.getBundle("userInfo");
String senderName = getSenderName(data);
if (userInfoBundle != null) {
boolean localPushNotificationTest = userInfoBundle.getBoolean("test");
if (localPushNotificationTest) {
senderName = "Test";
}
}
if (conversationTitle == null || !android.text.TextUtils.isEmpty(senderName.trim())) {
message = removeSenderNameFromMessage(message, senderName);
}
long timestamp = data.getLong("time");
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
messagingStyle.addMessage(message, timestamp, senderName);
} else {
Person sender = new Person.Builder()
.setKey(senderId)
.setName(senderName)
.build();
messagingStyle.addMessage(message, timestamp, sender);
}
}
}
private void setNotificationChannel(Notification.Builder notification, Bundle bundle) {
// If Android Oreo or above we need to register a channel
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
}
NotificationChannel notificationChannel = mHighImportanceChannel;
boolean testNotification = false;
boolean localNotification = false;
Bundle userInfoBundle = bundle.getBundle("userInfo");
if (userInfoBundle != null) {
testNotification = userInfoBundle.getBoolean("test");
localNotification = userInfoBundle.getBoolean("local");
}
if (mAppLifecycleFacade.isAppVisible() && !testNotification && !localNotification) {
notificationChannel = mMinImportanceChannel;
}
notification.setChannelId(notificationChannel.getId());
}
private void setNotificationBadgeIconType(Notification.Builder notification) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notification.setBadgeIconType(Notification.BADGE_ICON_SMALL);
}
}
private void setNotificationGroup(Notification.Builder notification) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
notification
.setGroup(GROUP_KEY_MESSAGES)
.setGroupSummary(true);
}
}
private void setNotificationSound(Notification.Builder notification, NotificationPreferences notificationPreferences) {
String soundUri = notificationPreferences.getNotificationSound();
if (soundUri != null) {
if (soundUri != "none") {
notification.setSound(Uri.parse(soundUri), AudioManager.STREAM_NOTIFICATION);
}
} else {
Uri defaultUri = System.DEFAULT_NOTIFICATION_URI;
notification.setSound(defaultUri, AudioManager.STREAM_NOTIFICATION);
}
}
private void setNotificationVibrate(Notification.Builder notification, NotificationPreferences notificationPreferences) {
boolean vibrate = notificationPreferences.getShouldVibrate();
if (vibrate) {
// Use the system default for vibration
notification.setDefaults(Notification.DEFAULT_VIBRATE);
}
}
private void setNotificationBlink(Notification.Builder notification, NotificationPreferences notificationPreferences) {
boolean blink = notificationPreferences.getShouldBlink();
if (blink) {
notification.setLights(Color.CYAN, 500, 500);
}
}
private void setNotificationDeleteIntent(Notification.Builder notification, int notificationId) {
// Let's add a delete intent when the notification is dismissed
Intent delIntent = new Intent(mContext, NotificationDismissService.class);
delIntent.putExtra(NOTIFICATION_ID, notificationId);
PendingIntent deleteIntent = NotificationIntentAdapter.createPendingNotificationIntent(mContext, delIntent, mNotificationProps);
notification.setDeleteIntent(deleteIntent);
}
private void addNotificationReplyAction(Notification.Builder notification, int notificationId, Bundle bundle) {
String postId = bundle.getString("post_id");
String serverUrl = bundle.getString("server_url", DatabaseHelper.getOnlyServerUrl(context));
if (android.text.TextUtils.isEmpty(postId) ||
serverUrl == null ||
Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
return;
}
Intent replyIntent = new Intent(mContext, NotificationReplyBroadcastReceiver.class);
replyIntent.setAction(KEY_TEXT_REPLY);
replyIntent.putExtra(NOTIFICATION_ID, notificationId);
replyIntent.putExtra(NOTIFICATION, bundle);
PendingIntent replyPendingIntent = PendingIntent.getBroadcast(
mContext,
notificationId,
replyIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
.setLabel("Reply")
.build();
int icon = R.drawable.ic_notif_action_reply;
CharSequence title = "Reply";
Notification.Action replyAction = new Notification.Action.Builder(icon, title, replyPendingIntent)
.addRemoteInput(remoteInput)
.setAllowGeneratedReplies(true)
.build();
notification
.setShowWhen(true)
.addAction(replyAction);
private void notificationReceiptDelivery(String ackId, String serverUrl, String postId, String type, boolean isIdLoaded, ResolvePromise promise) {
ReceiptDelivery.send(mContext, ackId, serverUrl, postId, type, isIdLoaded, promise);
}
private void notifyReceivedToJS() {
mJsIOHelper.sendEventToJS(NOTIFICATION_RECEIVED_EVENT_NAME, mNotificationProps.asBundle(), mAppLifecycleFacade.getRunningReactContext());
}
private void cancelNotification(Bundle data, int notificationId) {
final String channelId = data.getString("channel_id");
final String badge = data.getString("badge");
private String addServerUrlToBundle(Bundle bundle) {
String serverUrl = bundle.getString("server_url");
if (serverUrl == null) {
serverUrl = DatabaseHelper.getOnlyServerUrl(mContext);
bundle.putString("server_url", serverUrl);
mNotificationProps = createProps(bundle);
}
CustomPushNotification.badgeCount = Integer.parseInt(badge);
CustomPushNotification.clearNotification(mContext.getApplicationContext(), notificationId, channelId);
return serverUrl;
}
private String getSenderName(Bundle bundle) {
String senderName = bundle.getString("sender_name");
if (senderName != null) {
return senderName;
private static void saveNotificationsMap(Context context, Map<String, List<Integer>> inputMap) {
SharedPreferences pSharedPref = context.getSharedPreferences(PUSH_NOTIFICATIONS, Context.MODE_PRIVATE);
if (pSharedPref != null && context != null) {
JSONObject json = new JSONObject(inputMap);
String jsonString = json.toString();
SharedPreferences.Editor editor = pSharedPref.edit();
editor.remove(NOTIFICATIONS_IN_CHANNEL).commit();
editor.putString(NOTIFICATIONS_IN_CHANNEL, jsonString);
editor.commit();
}
}
String channelName = bundle.getString("channel_name");
if (channelName != null && channelName.startsWith("@")) {
return channelName;
}
String message = bundle.getString("message");
if (message != null) {
String name = message.split(":")[0];
if (name != message) {
return name;
private static Map<String, List<Integer>> loadNotificationsMap(Context context) {
Map<String, List<Integer>> outputMap = new HashMap<>();
if (context != null) {
SharedPreferences pSharedPref = context.getSharedPreferences(PUSH_NOTIFICATIONS, Context.MODE_PRIVATE);
try {
if (pSharedPref != null) {
String jsonString = pSharedPref.getString(NOTIFICATIONS_IN_CHANNEL, (new JSONObject()).toString());
JSONObject json = new JSONObject(jsonString);
Iterator<String> keysItr = json.keys();
while (keysItr.hasNext()) {
String key = keysItr.next();
JSONArray array = json.getJSONArray(key);
List<Integer> values = new ArrayList<>();
for (int i = 0; i < array.length(); ++i) {
values.add(array.getInt(i));
}
outputMap.put(key, values);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return getConversationTitle(bundle);
}
private String removeSenderNameFromMessage(String message, String senderName) {
Integer index = message.indexOf(senderName);
if (index == 0) {
message = message.substring(senderName.length());
}
return message.replaceFirst(": ", "").trim();
}
private void notificationReceiptDelivery(String ackId, String serverUrl, String postId, String type, boolean isIdLoaded, ResolvePromise promise) {
ReceiptDelivery.send(context, ackId, serverUrl, postId, type, isIdLoaded, promise);
}
private void createNotificationChannels() {
// Notification channels are not supported in Android Nougat and below
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
}
final NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mHighImportanceChannel = new NotificationChannel("channel_01", "High Importance", NotificationManager.IMPORTANCE_HIGH);
mHighImportanceChannel.setShowBadge(true);
notificationManager.createNotificationChannel(mHighImportanceChannel);
mMinImportanceChannel = new NotificationChannel("channel_02", "Min Importance", NotificationManager.IMPORTANCE_MIN);
mMinImportanceChannel.setShowBadge(true);
notificationManager.createNotificationChannel(mMinImportanceChannel);
return outputMap;
}
}

View File

@@ -6,6 +6,7 @@ import android.app.IntentService;
import android.os.Bundle;
import android.util.Log;
import com.mattermost.helpers.CustomPushNotificationHelper;
import com.wix.reactnativenotifications.core.NotificationIntentAdapter;
public class NotificationDismissService extends IntentService {
@@ -16,11 +17,18 @@ public class NotificationDismissService extends IntentService {
@Override
protected void onHandleIntent(Intent intent) {
mContext = getApplicationContext();
Bundle bundle = NotificationIntentAdapter.extractPendingNotificationDataFromIntent(intent);
int notificationId = intent.getIntExtra(CustomPushNotification.NOTIFICATION_ID, -1);
String channelId = bundle.getString("channel_id");
CustomPushNotification.clearNotification(mContext, notificationId, channelId);
final Context context = getApplicationContext();
final Bundle bundle = NotificationIntentAdapter.extractPendingNotificationDataFromIntent(intent);
final String channelId = bundle.getString("channel_id");
final String postId = bundle.getString("post_id");
int notificationId = CustomPushNotificationHelper.MESSAGE_NOTIFICATION_ID;
if (postId != null) {
notificationId = postId.hashCode();
} else if (channelId != null) {
notificationId = channelId.hashCode();
}
CustomPushNotification.cancelNotification(context, channelId, notificationId);
Log.i("ReactNative", "Dismiss notification");
}
}

View File

@@ -10,8 +10,7 @@ public class NotificationPreferences {
public final String SOUND_PREF = "NotificationSound";
public final String VIBRATE_PREF = "NotificationVibrate";
public final String BLINK_PREF = "NotificationLights";
private SharedPreferences mSharedPreferences;
private final SharedPreferences mSharedPreferences;
private NotificationPreferences(Context context) {
mSharedPreferences = context.getSharedPreferences(SHARED_NAME, Context.MODE_PRIVATE);
@@ -40,18 +39,18 @@ public class NotificationPreferences {
public void setNotificationSound(String soundUri) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putString(SOUND_PREF, soundUri);
editor.commit();
editor.apply();
}
public void setShouldVibrate(boolean vibrate) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(VIBRATE_PREF, vibrate);
editor.commit();
editor.apply();
}
public void setShouldBlink(boolean blink) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(BLINK_PREF, blink);
editor.commit();
editor.apply();
}
}

View File

@@ -21,7 +21,7 @@ import com.facebook.react.bridge.WritableMap;
public class NotificationPreferencesModule extends ReactContextBaseJavaModule {
private static NotificationPreferencesModule instance;
private final MainApplication mApplication;
private NotificationPreferences mNotificationPreference;
private final NotificationPreferences mNotificationPreference;
private NotificationPreferencesModule(MainApplication application, ReactApplicationContext reactContext) {
super(reactContext);
@@ -108,7 +108,7 @@ public class NotificationPreferencesModule extends ReactContextBaseJavaModule {
@ReactMethod
public void getDeliveredNotifications(final Promise promise) {
Context context = mApplication.getApplicationContext();
final Context context = mApplication.getApplicationContext();
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
StatusBarNotification[] statusBarNotifications = notificationManager.getActiveNotifications();
WritableArray result = Arguments.createArray();
@@ -116,9 +116,7 @@ public class NotificationPreferencesModule extends ReactContextBaseJavaModule {
WritableMap map = Arguments.createMap();
Notification n = sbn.getNotification();
Bundle bundle = n.extras;
int identifier = sbn.getId();
String channelId = bundle.getString("channel_id");
map.putInt("identifier", identifier);
map.putString("channel_id", channelId);
result.pushMap(map);
}
@@ -126,8 +124,8 @@ public class NotificationPreferencesModule extends ReactContextBaseJavaModule {
}
@ReactMethod
public void removeDeliveredNotifications(int identifier, String channelId) {
public void removeDeliveredNotifications(String channelId) {
Context context = mApplication.getApplicationContext();
CustomPushNotification.clearNotification(context, identifier, channelId);
CustomPushNotification.clearChannelNotifications(context, channelId);
}
}

View File

@@ -3,6 +3,7 @@ package com.mattermost.rnbeta;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -10,6 +11,9 @@ import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.Person;
import android.util.Log;
import java.io.IOException;
@@ -28,6 +32,8 @@ import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.WritableMap;
import com.wix.reactnativenotifications.core.NotificationIntentAdapter;
import com.wix.reactnativenotifications.core.ProxyService;
import com.wix.reactnativenotifications.core.notification.PushNotificationProps;
public class NotificationReplyBroadcastReceiver extends BroadcastReceiver {
private Context mContext;
@@ -47,27 +53,14 @@ public class NotificationReplyBroadcastReceiver extends BroadcastReceiver {
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
final ReactApplicationContext reactApplicationContext = new ReactApplicationContext(context);
final int notificationId = intent.getIntExtra(CustomPushNotification.NOTIFICATION_ID, -1);
final Bundle notification = intent.getBundleExtra(CustomPushNotification.NOTIFICATION);
final int notificationId = intent.getIntExtra(CustomPushNotificationHelper.NOTIFICATION_ID, -1);
final Bundle notification = intent.getBundleExtra(CustomPushNotificationHelper.NOTIFICATION);
final String serverUrl = notification.getString("serverUrl");
final String token = Credentials.getCredentialsForServerSync(reactApplicationContext, serverUrl);
Credentials.getCredentialsForServer(reactApplicationContext, serverUrl, new ResolvePromise() {
@Override
public void resolve(@Nullable Object value) {
if (value instanceof Boolean && !(Boolean)value) {
return;
}
WritableMap map = (WritableMap) value;
if (map != null) {
String token = map.getString("password");
String serverUrl = map.getString("service");
replyToMessage(serverUrl, token, notificationId, message);
}
}
});
if (token != null) {
replyToMessage(serverUrl, token, notificationId, message);
}
}
}
@@ -80,7 +73,7 @@ public class NotificationReplyBroadcastReceiver extends BroadcastReceiver {
}
if (token == null || serverUrl == null) {
onReplyFailed(notificationManager, notificationId, channelId);
onReplyFailed(notificationId);
return;
}
@@ -103,17 +96,17 @@ public class NotificationReplyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onFailure(Call call, IOException e) {
Log.i("ReactNative", String.format("Reply FAILED exception %s", e.getMessage()));
onReplyFailed(notificationManager, notificationId, channelId);
onReplyFailed(notificationId);
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
if (response.isSuccessful()) {
onReplySuccess(notificationManager, notificationId, channelId);
onReplySuccess(notificationId, message);
Log.i("ReactNative", "Reply SUCCESS");
} else {
Log.i("ReactNative", String.format("Reply FAILED status %s BODY %s", response.code(), response.body().string()));
onReplyFailed(notificationManager, notificationId, channelId);
onReplyFailed(notificationId);
}
}
});
@@ -131,37 +124,31 @@ public class NotificationReplyBroadcastReceiver extends BroadcastReceiver {
}
}
protected void onReplyFailed(NotificationManager notificationManager, int notificationId, String channelId) {
String CHANNEL_ID = "Reply job";
Resources res = mContext.getResources();
String packageName = mContext.getPackageName();
int smallIconResId = res.getIdentifier("ic_notification", "mipmap", packageName);
Bundle userInfoBundle = new Bundle();
userInfoBundle.putString("channel_id", channelId);
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
notificationManager.createNotificationChannel(channel);
Notification notification =
new Notification.Builder(mContext, CHANNEL_ID)
.setContentTitle("Message failed to send.")
.setSmallIcon(smallIconResId)
.addExtras(userInfoBundle)
.build();
CustomPushNotification.clearNotification(mContext, notificationId, channelId);
notificationManager.notify(notificationId, notification);
protected void onReplyFailed(int notificationId) {
recreateNotification(notificationId, "Message failed to send.");
}
protected void onReplySuccess(NotificationManager notificationManager, int notificationId, String channelId) {
notificationManager.cancel(notificationId);
CustomPushNotification.clearNotification(mContext, notificationId, channelId);
protected void onReplySuccess(int notificationId, final CharSequence message) {
recreateNotification(notificationId, message);
}
private void recreateNotification(int notificationId, final CharSequence message) {
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, false);
Notification notification = builder.build();
NotificationCompat.MessagingStyle messagingStyle = NotificationCompat.MessagingStyle.extractMessagingStyleFromNotification(notification);
assert messagingStyle != null;
messagingStyle.addMessage(message, System.currentTimeMillis(), (Person)null);
notification = builder.setStyle(messagingStyle).build();
notificationManager.notify(notificationId, notification);
}
private CharSequence getReplyMessage(Intent intent) {
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput != null) {
return remoteInput.getCharSequence(CustomPushNotification.KEY_TEXT_REPLY);
return remoteInput.getCharSequence(CustomPushNotificationHelper.KEY_TEXT_REPLY);
}
return null;
}

View File

@@ -26,31 +26,9 @@ public class ReceiptDelivery {
public static void send(Context context, final String ackId, final String serverUrl, final String postId, final String type, final boolean isIdLoaded, ResolvePromise promise) {
final ReactApplicationContext reactApplicationContext = new ReactApplicationContext(context);
Credentials.getCredentialsForServer(reactApplicationContext, serverUrl, new ResolvePromise() {
@Override
public void resolve(@Nullable Object value) {
if (value instanceof Boolean && !(Boolean)value) {
return;
}
WritableMap map = (WritableMap) value;
if (map != null) {
String token = map.getString("password");
String serverUrl = map.getString("service");
if (serverUrl.isEmpty()) {
String[] credentials = token.split(",[ ]*");
if (credentials.length == 2) {
token = credentials[0];
serverUrl = credentials[1];
}
}
Log.i("ReactNative", String.format("Send receipt delivery ACK=%s TYPE=%s to URL=%s with ID-LOADED=%s", ackId, type, serverUrl, isIdLoaded));
execute(serverUrl, postId, token, ackId, type, isIdLoaded, promise);
}
}
});
final String token = Credentials.getCredentialsForServerSync(reactApplicationContext, serverUrl);
Log.i("ReactNative", String.format("Send receipt delivery ACK=%s TYPE=%s to URL=%s with ID-LOADED=%s", ackId, type, serverUrl, isIdLoaded));
execute(serverUrl, postId, token, ackId, type, isIdLoaded, promise);
}
protected static void execute(String serverUrl, String postId, String token, String ackId, String type, boolean isIdLoaded, ResolvePromise promise) {
@@ -111,6 +89,8 @@ public class ReceiptDelivery {
return;
case 401:
promise.reject("Receipt delivery failure", "Unauthorized");
case 403:
promise.reject("Receipt delivery failure", "Forbidden");
return;
case 500:
promise.reject("Receipt delivery failure", "StatusInternalServerError");