[notifications] Android channel and channel group support
This commit is contained in:
parent
7acace4ce6
commit
b9df258402
|
@ -1,49 +0,0 @@
|
||||||
package io.invertase.firebase.messaging;
|
|
||||||
|
|
||||||
import android.app.AlarmManager;
|
|
||||||
import android.app.Application;
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
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.RingtoneManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v4.app.NotificationCompat;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
|
|
||||||
public class RNFirebaseLocalMessagingHelper {
|
|
||||||
private static final long DEFAULT_VIBRATION = 300L;
|
|
||||||
private static final String TAG = RNFirebaseLocalMessagingHelper.class.getSimpleName();
|
|
||||||
private final static String PREFERENCES_KEY = "ReactNativeSystemNotification";
|
|
||||||
private static boolean mIsForeground = false; //this is a hack
|
|
||||||
|
|
||||||
private Context mContext;
|
|
||||||
private SharedPreferences sharedPreferences = null;
|
|
||||||
|
|
||||||
public RNFirebaseLocalMessagingHelper(Application context) {
|
|
||||||
mContext = context;
|
|
||||||
sharedPreferences = mContext.getSharedPreferences(PREFERENCES_KEY, Context.MODE_PRIVATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setApplicationForeground(boolean foreground){
|
|
||||||
mIsForeground = foreground;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,16 +1,12 @@
|
||||||
package io.invertase.firebase.messaging;
|
package io.invertase.firebase.messaging;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.facebook.react.bridge.ActivityEventListener;
|
|
||||||
import com.facebook.react.bridge.Arguments;
|
import com.facebook.react.bridge.Arguments;
|
||||||
import com.facebook.react.bridge.Promise;
|
import com.facebook.react.bridge.Promise;
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
|
@ -18,32 +14,20 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||||
import com.facebook.react.bridge.ReactMethod;
|
import com.facebook.react.bridge.ReactMethod;
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
||||||
import com.facebook.react.bridge.WritableArray;
|
|
||||||
import com.facebook.react.bridge.WritableMap;
|
import com.facebook.react.bridge.WritableMap;
|
||||||
import com.google.firebase.iid.FirebaseInstanceId;
|
import com.google.firebase.iid.FirebaseInstanceId;
|
||||||
import com.google.firebase.messaging.FirebaseMessaging;
|
import com.google.firebase.messaging.FirebaseMessaging;
|
||||||
import com.google.firebase.messaging.RemoteMessage;
|
import com.google.firebase.messaging.RemoteMessage;
|
||||||
import com.google.firebase.messaging.RemoteMessage.Notification;
|
|
||||||
|
|
||||||
import io.invertase.firebase.Utils;
|
import io.invertase.firebase.Utils;
|
||||||
import me.leolin.shortcutbadger.ShortcutBadger;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements ActivityEventListener {
|
public class RNFirebaseMessaging extends ReactContextBaseJavaModule {
|
||||||
private static final String BADGE_FILE = "BadgeCountFile";
|
|
||||||
private static final String BADGE_KEY = "BadgeCount";
|
|
||||||
|
|
||||||
private static final String TAG = "RNFirebaseMessaging";
|
private static final String TAG = "RNFirebaseMessaging";
|
||||||
|
|
||||||
private SharedPreferences sharedPreferences = null;
|
|
||||||
|
|
||||||
public RNFirebaseMessaging(ReactApplicationContext context) {
|
public RNFirebaseMessaging(ReactApplicationContext context) {
|
||||||
super(context);
|
super(context);
|
||||||
context.addActivityEventListener(this);
|
|
||||||
|
|
||||||
sharedPreferences = context.getSharedPreferences(BADGE_FILE, Context.MODE_PRIVATE);
|
|
||||||
|
|
||||||
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
|
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
|
||||||
|
|
||||||
// Subscribe to message events
|
// Subscribe to message events
|
||||||
|
@ -73,24 +57,6 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements A
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non Web SDK methods
|
// Non Web SDK methods
|
||||||
|
|
||||||
@ReactMethod
|
|
||||||
public void getBadge(Promise promise) {
|
|
||||||
int badge = sharedPreferences.getInt(BADGE_KEY, 0);
|
|
||||||
Log.d(TAG, "Got badge count: " + badge);
|
|
||||||
promise.resolve(badge);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ReactMethod
|
|
||||||
public void getInitialMessage(Promise promise) {
|
|
||||||
if (getCurrentActivity() == null) {
|
|
||||||
promise.resolve(null);
|
|
||||||
} else {
|
|
||||||
WritableMap messageMap = parseIntentForMessage(getCurrentActivity().getIntent());
|
|
||||||
promise.resolve(messageMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void hasPermission(Promise promise) {
|
public void hasPermission(Promise promise) {
|
||||||
promise.resolve(true);
|
promise.resolve(true);
|
||||||
|
@ -132,19 +98,6 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements A
|
||||||
promise.resolve(null);
|
promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactMethod
|
|
||||||
public void setBadge(int badge) {
|
|
||||||
// Store the badge count for later retrieval
|
|
||||||
sharedPreferences.edit().putInt(BADGE_KEY, badge).apply();
|
|
||||||
if (badge == 0) {
|
|
||||||
Log.d(TAG, "Remove badge count");
|
|
||||||
ShortcutBadger.removeCount(this.getReactApplicationContext());
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "Apply badge count: " + badge);
|
|
||||||
ShortcutBadger.applyCount(this.getReactApplicationContext(), badge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void subscribeToTopic(String topic) {
|
public void subscribeToTopic(String topic) {
|
||||||
FirebaseMessaging.getInstance().subscribeToTopic(topic);
|
FirebaseMessaging.getInstance().subscribeToTopic(topic);
|
||||||
|
@ -155,60 +108,6 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements A
|
||||||
FirebaseMessaging.getInstance().unsubscribeFromTopic(topic);
|
FirebaseMessaging.getInstance().unsubscribeFromTopic(topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// Start ActivityEventListener methods
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
@Override
|
|
||||||
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
|
|
||||||
// FCM functionality does not need this function
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNewIntent(Intent intent) {
|
|
||||||
WritableMap messageMap = parseIntentForMessage(intent);
|
|
||||||
if (messageMap != null) {
|
|
||||||
Log.d(TAG, "onNewIntent called with new FCM message");
|
|
||||||
Utils.sendEvent(getReactApplicationContext(), "messaging_message_received", messageMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// End ActivityEventListener methods
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private WritableMap parseIntentForMessage(Intent intent) {
|
|
||||||
// Check if FCM data exists
|
|
||||||
if (intent.getExtras() == null || !intent.hasExtra("google.message_id")) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bundle extras = intent.getExtras();
|
|
||||||
|
|
||||||
WritableMap messageMap = Arguments.createMap();
|
|
||||||
WritableMap dataMap = Arguments.createMap();
|
|
||||||
|
|
||||||
for (String key : extras.keySet()) {
|
|
||||||
if (key.equals("collapse_key")) {
|
|
||||||
messageMap.putString("collapseKey", extras.getString("collapse_key"));
|
|
||||||
} else if (key.equals("from")) {
|
|
||||||
messageMap.putString("from", extras.getString("from"));
|
|
||||||
} else if (key.equals("google.message_id")) {
|
|
||||||
messageMap.putString("messageId", extras.getString("google.message_id"));
|
|
||||||
} else if (key.equals("google.sent_time")) {
|
|
||||||
messageMap.putDouble("sentTime", extras.getLong("google.sent_time"));
|
|
||||||
} else if (key.equals("google.ttl")) {
|
|
||||||
messageMap.putDouble("ttl", extras.getDouble("google.ttl"));
|
|
||||||
} else if (key.equals("_fbSourceApplicationHasBeenSet")) {
|
|
||||||
// ignore known unneeded fields
|
|
||||||
} else {
|
|
||||||
dataMap.putString(key, extras.getString(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
messageMap.putMap("data", dataMap);
|
|
||||||
messageMap.putBoolean("openedFromTray", true);
|
|
||||||
|
|
||||||
return messageMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class MessageReceiver extends BroadcastReceiver {
|
private class MessageReceiver extends BroadcastReceiver {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
@ -246,67 +145,10 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements A
|
||||||
if (message.getMessageType() != null) {
|
if (message.getMessageType() != null) {
|
||||||
messageMap.putString("messageType", message.getMessageType());
|
messageMap.putString("messageType", message.getMessageType());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.getNotification() != null) {
|
|
||||||
Notification notification = message.getNotification();
|
|
||||||
|
|
||||||
WritableMap notificationMap = Arguments.createMap();
|
|
||||||
|
|
||||||
if (notification.getBody() != null) {
|
|
||||||
notificationMap.putString("body", notification.getBody());
|
|
||||||
}
|
|
||||||
if (notification.getBodyLocalizationArgs() != null) {
|
|
||||||
WritableArray bodyArgs = Arguments.createArray();
|
|
||||||
for (String arg : notification.getBodyLocalizationArgs()) {
|
|
||||||
bodyArgs.pushString(arg);
|
|
||||||
}
|
|
||||||
notificationMap.putArray("bodyLocalizationArgs", bodyArgs);
|
|
||||||
}
|
|
||||||
if (notification.getBodyLocalizationKey() != null) {
|
|
||||||
notificationMap.putString("bodyLocalizationKey", notification.getBodyLocalizationKey());
|
|
||||||
}
|
|
||||||
if (notification.getClickAction() != null) {
|
|
||||||
notificationMap.putString("clickAction", notification.getClickAction());
|
|
||||||
}
|
|
||||||
if (notification.getColor() != null) {
|
|
||||||
notificationMap.putString("color", notification.getColor());
|
|
||||||
}
|
|
||||||
if (notification.getIcon() != null) {
|
|
||||||
notificationMap.putString("icon", notification.getIcon());
|
|
||||||
}
|
|
||||||
if (notification.getLink() != null) {
|
|
||||||
notificationMap.putString("link", notification.getLink().toString());
|
|
||||||
}
|
|
||||||
if (notification.getSound() != null) {
|
|
||||||
notificationMap.putString("sound", notification.getSound());
|
|
||||||
}
|
|
||||||
if (notification.getTag() != null) {
|
|
||||||
notificationMap.putString("tag", notification.getTag());
|
|
||||||
}
|
|
||||||
if (notification.getTitle() != null) {
|
|
||||||
notificationMap.putString("title", notification.getTitle());
|
|
||||||
}
|
|
||||||
if (notification.getTitleLocalizationArgs() != null) {
|
|
||||||
WritableArray titleArgs = Arguments.createArray();
|
|
||||||
for (String arg : notification.getTitleLocalizationArgs()) {
|
|
||||||
titleArgs.pushString(arg);
|
|
||||||
}
|
|
||||||
notificationMap.putArray("titleLocalizationArgs", titleArgs);
|
|
||||||
}
|
|
||||||
if (notification.getTitleLocalizationKey() != null) {
|
|
||||||
notificationMap.putString("titleLocalizationKey", notification.getTitleLocalizationKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
messageMap.putMap("notification", notificationMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
messageMap.putBoolean("openedFromTray", false);
|
|
||||||
messageMap.putDouble("sentTime", message.getSentTime());
|
messageMap.putDouble("sentTime", message.getSentTime());
|
||||||
|
|
||||||
if (message.getTo() != null) {
|
if (message.getTo() != null) {
|
||||||
messageMap.putString("to", message.getTo());
|
messageMap.putString("to", message.getTo());
|
||||||
}
|
}
|
||||||
|
|
||||||
messageMap.putDouble("ttl", message.getTtl());
|
messageMap.putDouble("ttl", message.getTtl());
|
||||||
|
|
||||||
return messageMap;
|
return messageMap;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package io.invertase.firebase.messaging;
|
package io.invertase.firebase.messaging;
|
||||||
|
|
||||||
import com.facebook.react.ReactPackage;
|
import com.facebook.react.ReactPackage;
|
||||||
import com.facebook.react.bridge.JavaScriptModule;
|
|
||||||
import com.facebook.react.bridge.NativeModule;
|
import com.facebook.react.bridge.NativeModule;
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.uimanager.UIManagerModule;
|
import com.facebook.react.uimanager.UIManagerModule;
|
||||||
|
|
|
@ -10,16 +10,25 @@ import com.google.firebase.messaging.RemoteMessage;
|
||||||
public class RNFirebaseMessagingService extends FirebaseMessagingService {
|
public class RNFirebaseMessagingService extends FirebaseMessagingService {
|
||||||
private static final String TAG = "RNFMessagingService";
|
private static final String TAG = "RNFMessagingService";
|
||||||
public static final String MESSAGE_EVENT = "messaging-message";
|
public static final String MESSAGE_EVENT = "messaging-message";
|
||||||
|
public static final String REMOTE_NOTIFICATION_EVENT = "notifications-remote-notification";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessageReceived(RemoteMessage message) {
|
public void onMessageReceived(RemoteMessage message) {
|
||||||
Log.d(TAG, "onMessageReceived event received");
|
Log.d(TAG, "onMessageReceived event received");
|
||||||
|
|
||||||
// Build an Intent to pass the token to the RN Application
|
Intent event;
|
||||||
Intent messageEvent = new Intent(MESSAGE_EVENT);
|
|
||||||
messageEvent.putExtra("message", message);
|
if (message.getNotification() != null) {
|
||||||
|
// It's a notification, pass to the notification module
|
||||||
|
event = new Intent(REMOTE_NOTIFICATION_EVENT);
|
||||||
|
event.putExtra("notification", message);
|
||||||
|
} else {
|
||||||
|
// It's a data message, pass to the messaging module
|
||||||
|
event = new Intent(MESSAGE_EVENT);
|
||||||
|
event.putExtra("message", message);
|
||||||
|
}
|
||||||
|
|
||||||
// Broadcast it so it is only available to the RN Application
|
// Broadcast it so it is only available to the RN Application
|
||||||
LocalBroadcastManager.getInstance(this).sendBroadcast(messageEvent);
|
LocalBroadcastManager.getInstance(this).sendBroadcast(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ package io.invertase.firebase.notifications;
|
||||||
|
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationChannel;
|
||||||
|
import android.app.NotificationChannelGroup;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -21,6 +23,7 @@ import android.util.Log;
|
||||||
|
|
||||||
import com.facebook.react.bridge.Arguments;
|
import com.facebook.react.bridge.Arguments;
|
||||||
import com.facebook.react.bridge.Promise;
|
import com.facebook.react.bridge.Promise;
|
||||||
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
@ -30,6 +33,7 @@ import java.io.IOException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import io.invertase.firebase.messaging.BundleJSONConverter;
|
import io.invertase.firebase.messaging.BundleJSONConverter;
|
||||||
|
@ -71,6 +75,42 @@ public class RNFirebaseNotificationManager {
|
||||||
preferences.edit().remove(notificationId).apply();
|
preferences.edit().remove(notificationId).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void createChannel(ReadableMap channelMap) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
NotificationChannel channel = parseChannelMap(channelMap);
|
||||||
|
notificationManager.createNotificationChannel(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createChannelGroup(ReadableMap channelGroupMap) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
NotificationChannelGroup channelGroup = parseChannelGroupMap(channelGroupMap);
|
||||||
|
notificationManager.createNotificationChannelGroup(channelGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createChannelGroups(ReadableArray channelGroupsArray) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
List<NotificationChannelGroup> channelGroups = new ArrayList<>();
|
||||||
|
for (int i = 0; i < channelGroupsArray.size(); i++) {
|
||||||
|
NotificationChannelGroup channelGroup = parseChannelGroupMap(channelGroupsArray.getMap(i));
|
||||||
|
channelGroups.add(channelGroup);
|
||||||
|
}
|
||||||
|
notificationManager.createNotificationChannelGroups(channelGroups);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createChannels(ReadableArray channelsArray) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
List<NotificationChannel> channels = new ArrayList<>();
|
||||||
|
for (int i = 0; i < channelsArray.size(); i++) {
|
||||||
|
NotificationChannel channel = parseChannelMap(channelsArray.getMap(i));
|
||||||
|
channels.add(channel);
|
||||||
|
}
|
||||||
|
notificationManager.createNotificationChannels(channels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void displayNotification(ReadableMap notification, Promise promise) {
|
public void displayNotification(ReadableMap notification, Promise promise) {
|
||||||
Bundle notificationBundle = Arguments.toBundle(notification);
|
Bundle notificationBundle = Arguments.toBundle(notification);
|
||||||
displayNotification(notificationBundle, promise);
|
displayNotification(notificationBundle, promise);
|
||||||
|
@ -155,12 +195,14 @@ public class RNFirebaseNotificationManager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String channelId = notification.getString("channelId");
|
Bundle android = notification.getBundle("android");
|
||||||
|
|
||||||
|
String channelId = android.getString("channelId");
|
||||||
String notificationId = notification.getString("notificationId");
|
String notificationId = notification.getString("notificationId");
|
||||||
|
|
||||||
NotificationCompat.Builder nb;
|
NotificationCompat.Builder nb;
|
||||||
// TODO: Change 27 to 'Build.VERSION_CODES.O_MR1' when using appsupport v27
|
// TODO: Change 27 to 'Build.VERSION_CODES.O_MR1' when using appsupport v27
|
||||||
if (Build.VERSION.SDK_INT >= 27) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
nb = new NotificationCompat.Builder(context, channelId);
|
nb = new NotificationCompat.Builder(context, channelId);
|
||||||
} else {
|
} else {
|
||||||
nb = new NotificationCompat.Builder(context);
|
nb = new NotificationCompat.Builder(context);
|
||||||
|
@ -173,16 +215,8 @@ public class RNFirebaseNotificationManager {
|
||||||
nb = nb.setExtras(notification.getBundle("data"));
|
nb = nb.setExtras(notification.getBundle("data"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("sound")) {
|
if (notification.containsKey("sound")) {
|
||||||
String sound = notification.getString("sound");
|
Uri sound = getSound(notification.getString("sound"));
|
||||||
if (sound.equalsIgnoreCase("default")) {
|
nb = nb.setSound(sound);
|
||||||
nb = nb.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
|
|
||||||
} else {
|
|
||||||
int soundResourceId = getResourceId("raw", sound);
|
|
||||||
if (soundResourceId == 0) {
|
|
||||||
soundResourceId = getResourceId("raw", sound.substring(0, sound.lastIndexOf('.')));
|
|
||||||
}
|
|
||||||
nb = nb.setSound(Uri.parse("android.resource://" + context.getPackageName() + "/" + soundResourceId));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (notification.containsKey("subtitle")) {
|
if (notification.containsKey("subtitle")) {
|
||||||
nb = nb.setSubText(notification.getString("subtitle"));
|
nb = nb.setSubText(notification.getString("subtitle"));
|
||||||
|
@ -191,125 +225,138 @@ public class RNFirebaseNotificationManager {
|
||||||
nb = nb.setContentTitle(notification.getString("title"));
|
nb = nb.setContentTitle(notification.getString("title"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notification.containsKey("autoCancel")) {
|
if (android.containsKey("autoCancel")) {
|
||||||
nb = nb.setAutoCancel(notification.getBoolean("autoCancel"));
|
nb = nb.setAutoCancel(android.getBoolean("autoCancel"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("badgeIconType")) {
|
if (android.containsKey("badgeIconType")) {
|
||||||
nb = nb.setBadgeIconType(notification.getInt("badgeIconType"));
|
Double badgeIconType = android.getDouble("badgeIconType");
|
||||||
|
nb = nb.setBadgeIconType(badgeIconType.intValue());
|
||||||
}
|
}
|
||||||
if (notification.containsKey("category")) {
|
if (android.containsKey("category")) {
|
||||||
nb = nb.setCategory(notification.getString("category"));
|
nb = nb.setCategory(android.getString("category"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("color")) {
|
if (android.containsKey("color")) {
|
||||||
String color = notification.getString("color");
|
String color = android.getString("color");
|
||||||
nb = nb.setColor(Color.parseColor(color));
|
nb = nb.setColor(Color.parseColor(color));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("colorized")) {
|
if (android.containsKey("colorized")) {
|
||||||
nb = nb.setColorized(notification.getBoolean("colorized"));
|
nb = nb.setColorized(android.getBoolean("colorized"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("contentInfo")) {
|
if (android.containsKey("contentInfo")) {
|
||||||
nb = nb.setContentInfo(notification.getString("contentInfo"));
|
nb = nb.setContentInfo(android.getString("contentInfo"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("defaults")) {
|
if (notification.containsKey("defaults")) {
|
||||||
int[] defaultsArray = notification.getIntArray("defaults");
|
double[] defaultsArray = android.getDoubleArray("defaults");
|
||||||
int defaults = 0;
|
int defaults = 0;
|
||||||
for (int d : defaultsArray) {
|
for (Double d : defaultsArray) {
|
||||||
defaults |= d;
|
defaults |= d.intValue();
|
||||||
}
|
}
|
||||||
nb = nb.setDefaults(defaults);
|
nb = nb.setDefaults(defaults);
|
||||||
}
|
}
|
||||||
if (notification.containsKey("group")) {
|
if (android.containsKey("group")) {
|
||||||
nb = nb.setGroup(notification.getString("group"));
|
nb = nb.setGroup(android.getString("group"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("groupAlertBehaviour")) {
|
if (android.containsKey("groupAlertBehaviour")) {
|
||||||
nb = nb.setGroupAlertBehavior(notification.getInt("groupAlertBehaviour"));
|
Double groupAlertBehaviour = android.getDouble("groupAlertBehaviour");
|
||||||
|
nb = nb.setGroupAlertBehavior(groupAlertBehaviour.intValue());
|
||||||
}
|
}
|
||||||
if (notification.containsKey("groupSummary")) {
|
if (android.containsKey("groupSummary")) {
|
||||||
nb = nb.setGroupSummary(notification.getBoolean("groupSummary"));
|
nb = nb.setGroupSummary(android.getBoolean("groupSummary"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("largeIcon")) {
|
if (android.containsKey("largeIcon")) {
|
||||||
Bitmap largeIcon = getBitmap(notification.getString("largeIcon"));
|
Bitmap largeIcon = getBitmap(android.getString("largeIcon"));
|
||||||
if (largeIcon != null) {
|
if (largeIcon != null) {
|
||||||
nb = nb.setLargeIcon(largeIcon);
|
nb = nb.setLargeIcon(largeIcon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (notification.containsKey("lights")) {
|
if (android.containsKey("lights")) {
|
||||||
Bundle lights = notification.getBundle("lights");
|
Bundle lights = android.getBundle("lights");
|
||||||
nb = nb.setLights(lights.getInt("argb"), lights.getInt("onMs"), lights.getInt("offMs"));
|
Double argb = lights.getDouble("argb");
|
||||||
|
Double onMs = lights.getDouble("onMs");
|
||||||
|
Double offMs = lights.getDouble("offMs");
|
||||||
|
nb = nb.setLights(argb.intValue(), onMs.intValue(), offMs.intValue());
|
||||||
}
|
}
|
||||||
if (notification.containsKey("localOnly")) {
|
if (android.containsKey("localOnly")) {
|
||||||
nb = nb.setLocalOnly(notification.getBoolean("localOnly"));
|
nb = nb.setLocalOnly(android.getBoolean("localOnly"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notification.containsKey("number")) {
|
if (android.containsKey("number")) {
|
||||||
nb = nb.setNumber(notification.getInt("number"));
|
Double number = android.getDouble("number");
|
||||||
|
nb = nb.setNumber(number.intValue());
|
||||||
}
|
}
|
||||||
if (notification.containsKey("ongoing")) {
|
if (android.containsKey("ongoing")) {
|
||||||
nb = nb.setOngoing(notification.getBoolean("ongoing"));
|
nb = nb.setOngoing(android.getBoolean("ongoing"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("onlyAlertOnce")) {
|
if (android.containsKey("onlyAlertOnce")) {
|
||||||
nb = nb.setOngoing(notification.getBoolean("onlyAlertOnce"));
|
nb = nb.setOngoing(android.getBoolean("onlyAlertOnce"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("people")) {
|
if (android.containsKey("people")) {
|
||||||
String[] people = notification.getStringArray("people");
|
String[] people = android.getStringArray("people");
|
||||||
for (String person : people) {
|
if (people != null) {
|
||||||
nb = nb.addPerson(person);
|
for (String person : people) {
|
||||||
|
nb = nb.addPerson(person);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (notification.containsKey("priority")) {
|
if (android.containsKey("priority")) {
|
||||||
nb = nb.setPriority(notification.getInt("priority"));
|
Double priority = android.getDouble("priority");
|
||||||
|
nb = nb.setPriority(priority.intValue());
|
||||||
}
|
}
|
||||||
if (notification.containsKey("progress")) {
|
if (android.containsKey("progress")) {
|
||||||
Bundle progress = notification.getBundle("lights");
|
Bundle progress = android.getBundle("lights");
|
||||||
nb = nb.setProgress(progress.getInt("max"), progress.getInt("progress"), progress.getBoolean("indeterminate"));
|
Double max = progress.getDouble("max");
|
||||||
|
Double progressI = progress.getDouble("progress");
|
||||||
|
nb = nb.setProgress(max.intValue(), progressI.intValue(), progress.getBoolean("indeterminate"));
|
||||||
}
|
}
|
||||||
// TODO: Public version of notification
|
// TODO: Public version of notification
|
||||||
/* if (notification.containsKey("publicVersion")) {
|
/* if (android.containsKey("publicVersion")) {
|
||||||
nb = nb.setPublicVersion();
|
nb = nb.setPublicVersion();
|
||||||
} */
|
} */
|
||||||
if (notification.containsKey("remoteInputHistory")) {
|
if (android.containsKey("remoteInputHistory")) {
|
||||||
nb = nb.setRemoteInputHistory(notification.getStringArray("remoteInputHistory"));
|
nb = nb.setRemoteInputHistory(android.getStringArray("remoteInputHistory"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("shortcutId")) {
|
if (android.containsKey("shortcutId")) {
|
||||||
nb = nb.setShortcutId(notification.getString("shortcutId"));
|
nb = nb.setShortcutId(android.getString("shortcutId"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("showWhen")) {
|
if (android.containsKey("showWhen")) {
|
||||||
nb = nb.setShowWhen(notification.getBoolean("showWhen"));
|
nb = nb.setShowWhen(android.getBoolean("showWhen"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("smallIcon")) {
|
if (android.containsKey("smallIcon")) {
|
||||||
Bundle smallIcon = notification.getBundle("smallIcon");
|
Bundle smallIcon = android.getBundle("smallIcon");
|
||||||
int smallIconResourceId = getResourceId("mipmap", smallIcon.getString("icon"));
|
int smallIconResourceId = getResourceId("mipmap", smallIcon.getString("icon"));
|
||||||
if (smallIconResourceId == 0) {
|
if (smallIconResourceId == 0) {
|
||||||
smallIconResourceId = getResourceId("drawable", smallIcon.getString("icon"));
|
smallIconResourceId = getResourceId("drawable", smallIcon.getString("icon"));
|
||||||
}
|
}
|
||||||
if (smallIconResourceId != 0) {
|
if (smallIconResourceId != 0) {
|
||||||
if (smallIcon.containsKey("level")) {
|
if (smallIcon.containsKey("level")) {
|
||||||
nb = nb.setSmallIcon(smallIconResourceId, smallIcon.getInt("level"));
|
Double level = smallIcon.getDouble("level");
|
||||||
|
nb = nb.setSmallIcon(smallIconResourceId, level.intValue());
|
||||||
} else {
|
} else {
|
||||||
nb = nb.setSmallIcon(smallIconResourceId);
|
nb = nb.setSmallIcon(smallIconResourceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (notification.containsKey("sortKey")) {
|
if (android.containsKey("sortKey")) {
|
||||||
nb = nb.setSortKey(notification.getString("sortKey"));
|
nb = nb.setSortKey(android.getString("sortKey"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("ticker")) {
|
if (android.containsKey("ticker")) {
|
||||||
nb = nb.setTicker(notification.getString("ticker"));
|
nb = nb.setTicker(android.getString("ticker"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("timeoutAfter")) {
|
if (android.containsKey("timeoutAfter")) {
|
||||||
nb = nb.setTimeoutAfter(notification.getLong("timeoutAfter"));
|
nb = nb.setTimeoutAfter(android.getLong("timeoutAfter"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("usesChronometer")) {
|
if (android.containsKey("usesChronometer")) {
|
||||||
nb = nb.setUsesChronometer(notification.getBoolean("usesChronometer"));
|
nb = nb.setUsesChronometer(android.getBoolean("usesChronometer"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("vibrate")) {
|
if (android.containsKey("vibrate")) {
|
||||||
nb = nb.setVibrate(notification.getLongArray("vibrate"));
|
nb = nb.setVibrate(android.getLongArray("vibrate"));
|
||||||
}
|
}
|
||||||
if (notification.containsKey("visibility")) {
|
if (android.containsKey("visibility")) {
|
||||||
nb = nb.setVisibility(notification.getInt("visibility"));
|
Double visibility = android.getDouble("visibility");
|
||||||
|
nb = nb.setVisibility(visibility.intValue());
|
||||||
}
|
}
|
||||||
if (notification.containsKey("when")) {
|
if (android.containsKey("when")) {
|
||||||
nb = nb.setWhen(notification.getLong("when"));
|
nb = nb.setWhen(android.getLong("when"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Big text / Big picture
|
// TODO: Big text / Big picture
|
||||||
|
@ -335,8 +382,8 @@ public class RNFirebaseNotificationManager {
|
||||||
Intent intent = new Intent(context, intentClass);
|
Intent intent = new Intent(context, intentClass);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
intent.putExtras(notification);
|
intent.putExtras(notification);
|
||||||
if (notification.containsKey("clickAction")) {
|
if (android.containsKey("clickAction")) {
|
||||||
intent.setAction(notification.getString("clickAction"));
|
intent.setAction(android.getString("clickAction"));
|
||||||
}
|
}
|
||||||
|
|
||||||
PendingIntent contentIntent = PendingIntent.getActivity(context, notificationId.hashCode(), intent,
|
PendingIntent contentIntent = PendingIntent.getActivity(context, notificationId.hashCode(), intent,
|
||||||
|
@ -391,6 +438,71 @@ public class RNFirebaseNotificationManager {
|
||||||
return context.getResources().getIdentifier(image, type, context.getPackageName());
|
return context.getResources().getIdentifier(image, type, context.getPackageName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Uri getSound(String sound) {
|
||||||
|
if (sound.equalsIgnoreCase("default")) {
|
||||||
|
return RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||||
|
} else {
|
||||||
|
int soundResourceId = getResourceId("raw", sound);
|
||||||
|
if (soundResourceId == 0) {
|
||||||
|
soundResourceId = getResourceId("raw", sound.substring(0, sound.lastIndexOf('.')));
|
||||||
|
}
|
||||||
|
return Uri.parse("android.resource://" + context.getPackageName() + "/" + soundResourceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private NotificationChannelGroup parseChannelGroupMap(ReadableMap channelGroupMap) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
String groupId = channelGroupMap.getString("groupId");
|
||||||
|
String name = channelGroupMap.getString("name");
|
||||||
|
|
||||||
|
return new NotificationChannelGroup(groupId, name);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private NotificationChannel parseChannelMap(ReadableMap channelMap) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
String channelId = channelMap.getString("channelId");
|
||||||
|
String name = channelMap.getString("name");
|
||||||
|
int importance = channelMap.getInt("importance");
|
||||||
|
|
||||||
|
NotificationChannel channel = new NotificationChannel(channelId, name, importance);
|
||||||
|
if (channelMap.hasKey("bypassDnd")) {
|
||||||
|
channel.setBypassDnd(channelMap.getBoolean("bypassDnd"));
|
||||||
|
}
|
||||||
|
if (channelMap.hasKey("description")) {
|
||||||
|
channel.setDescription(channelMap.getString("description"));
|
||||||
|
}
|
||||||
|
if (channelMap.hasKey("group")) {
|
||||||
|
channel.setGroup(channelMap.getString("group"));
|
||||||
|
}
|
||||||
|
if (channelMap.hasKey("lightColor")) {
|
||||||
|
String lightColor = channelMap.getString("lightColor");
|
||||||
|
channel.setLightColor(Color.parseColor(lightColor));
|
||||||
|
}
|
||||||
|
if (channelMap.hasKey("lockScreenVisibility")) {
|
||||||
|
channel.setLockscreenVisibility(channelMap.getInt("lockScreenVisibility"));
|
||||||
|
}
|
||||||
|
if (channelMap.hasKey("showBadge")) {
|
||||||
|
channel.setShowBadge(channelMap.getBoolean("showBadge"));
|
||||||
|
}
|
||||||
|
if (channelMap.hasKey("sound")) {
|
||||||
|
Uri sound = getSound(channelMap.getString("sound"));
|
||||||
|
channel.setSound(sound, null);
|
||||||
|
}
|
||||||
|
if (channelMap.hasKey("vibrationPattern")) {
|
||||||
|
ReadableArray vibrationArray = channelMap.getArray("vibrationPattern");
|
||||||
|
long[] vibration = new long[]{};
|
||||||
|
for (int i = 0; i < vibrationArray.size(); i++) {
|
||||||
|
vibration[i] = (long) vibrationArray.getDouble(i);
|
||||||
|
}
|
||||||
|
channel.setVibrationPattern(vibration);
|
||||||
|
}
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void scheduleNotification(Bundle notification, Promise promise) {
|
private void scheduleNotification(Bundle notification, Promise promise) {
|
||||||
if (!notification.containsKey("notificationId")) {
|
if (!notification.containsKey("notificationId")) {
|
||||||
if (promise == null) {
|
if (promise == null) {
|
||||||
|
|
|
@ -1,38 +1,57 @@
|
||||||
package io.invertase.firebase.notifications;
|
package io.invertase.firebase.notifications;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.facebook.react.bridge.ActivityEventListener;
|
||||||
import com.facebook.react.bridge.Arguments;
|
import com.facebook.react.bridge.Arguments;
|
||||||
import com.facebook.react.bridge.LifecycleEventListener;
|
import com.facebook.react.bridge.LifecycleEventListener;
|
||||||
import com.facebook.react.bridge.Promise;
|
import com.facebook.react.bridge.Promise;
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||||
import com.facebook.react.bridge.ReactMethod;
|
import com.facebook.react.bridge.ReactMethod;
|
||||||
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
import com.facebook.react.bridge.WritableArray;
|
import com.facebook.react.bridge.WritableArray;
|
||||||
import com.facebook.react.bridge.WritableMap;
|
import com.facebook.react.bridge.WritableMap;
|
||||||
|
import com.google.firebase.messaging.RemoteMessage;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import io.invertase.firebase.Utils;
|
import io.invertase.firebase.Utils;
|
||||||
|
import io.invertase.firebase.messaging.RNFirebaseMessagingService;
|
||||||
|
import me.leolin.shortcutbadger.ShortcutBadger;
|
||||||
|
|
||||||
public class RNFirebaseNotifications extends ReactContextBaseJavaModule implements LifecycleEventListener {
|
public class RNFirebaseNotifications extends ReactContextBaseJavaModule implements ActivityEventListener, LifecycleEventListener {
|
||||||
|
private static final String BADGE_FILE = "BadgeCountFile";
|
||||||
|
private static final String BADGE_KEY = "BadgeCount";
|
||||||
private static final String TAG = "RNFirebaseNotifications";
|
private static final String TAG = "RNFirebaseNotifications";
|
||||||
|
|
||||||
|
private SharedPreferences sharedPreferences = null;
|
||||||
|
|
||||||
private RNFirebaseNotificationManager notificationManager;
|
private RNFirebaseNotificationManager notificationManager;
|
||||||
public RNFirebaseNotifications(ReactApplicationContext context) {
|
public RNFirebaseNotifications(ReactApplicationContext context) {
|
||||||
super(context);
|
super(context);
|
||||||
notificationManager = new RNFirebaseNotificationManager(context.getApplicationContext());
|
context.addActivityEventListener(this);
|
||||||
context.addLifecycleEventListener(this);
|
context.addLifecycleEventListener(this);
|
||||||
|
|
||||||
|
notificationManager = new RNFirebaseNotificationManager(context.getApplicationContext());
|
||||||
|
sharedPreferences = context.getSharedPreferences(BADGE_FILE, Context.MODE_PRIVATE);
|
||||||
|
|
||||||
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
|
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
|
||||||
|
|
||||||
|
// Subscribe to remote notification events
|
||||||
|
localBroadcastManager.registerReceiver(new RemoteNotificationReceiver(),
|
||||||
|
new IntentFilter(RNFirebaseMessagingService.REMOTE_NOTIFICATION_EVENT));
|
||||||
|
|
||||||
// Subscribe to scheduled notification events
|
// Subscribe to scheduled notification events
|
||||||
localBroadcastManager.registerReceiver(new ScheduledNotificationReceiver(),
|
localBroadcastManager.registerReceiver(new ScheduledNotificationReceiver(),
|
||||||
new IntentFilter(RNFirebaseNotificationManager.SCHEDULED_NOTIFICATION_EVENT));
|
new IntentFilter(RNFirebaseNotificationManager.SCHEDULED_NOTIFICATION_EVENT));
|
||||||
|
@ -58,9 +77,22 @@ public class RNFirebaseNotifications extends ReactContextBaseJavaModule implemen
|
||||||
notificationManager.displayNotification(notification, promise);
|
notificationManager.displayNotification(notification, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void getBadge(Promise promise) {
|
||||||
|
int badge = sharedPreferences.getInt(BADGE_KEY, 0);
|
||||||
|
Log.d(TAG, "Got badge count: " + badge);
|
||||||
|
promise.resolve(badge);
|
||||||
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void getInitialNotification(Promise promise) {
|
public void getInitialNotification(Promise promise) {
|
||||||
// TODO
|
// TODO
|
||||||
|
if (getCurrentActivity() == null) {
|
||||||
|
promise.resolve(null);
|
||||||
|
} else {
|
||||||
|
WritableMap notificationOpenedMap = parseIntentForRemoteNotification(getCurrentActivity().getIntent());
|
||||||
|
promise.resolve(notificationOpenedMap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
|
@ -83,11 +115,74 @@ public class RNFirebaseNotifications extends ReactContextBaseJavaModule implemen
|
||||||
notificationManager.removeDeliveredNotification(notificationId);
|
notificationManager.removeDeliveredNotification(notificationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void setBadge(int badge) {
|
||||||
|
// Store the badge count for later retrieval
|
||||||
|
sharedPreferences.edit().putInt(BADGE_KEY, badge).apply();
|
||||||
|
if (badge == 0) {
|
||||||
|
Log.d(TAG, "Remove badge count");
|
||||||
|
ShortcutBadger.removeCount(this.getReactApplicationContext());
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Apply badge count: " + badge);
|
||||||
|
ShortcutBadger.applyCount(this.getReactApplicationContext(), badge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void scheduleNotification(ReadableMap notification, Promise promise) {
|
public void scheduleNotification(ReadableMap notification, Promise promise) {
|
||||||
notificationManager.scheduleNotification(notification, promise);
|
notificationManager.scheduleNotification(notification, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Start Android specific methods
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
@ReactMethod
|
||||||
|
public void createChannel(ReadableMap channelMap, Promise promise) {
|
||||||
|
notificationManager.createChannel(channelMap);
|
||||||
|
promise.resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void createChannelGroup(ReadableMap channelGroupMap, Promise promise) {
|
||||||
|
notificationManager.createChannelGroup(channelGroupMap);
|
||||||
|
promise.resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void createChannelGroup(ReadableArray channelGroupsArray, Promise promise) {
|
||||||
|
notificationManager.createChannelGroups(channelGroupsArray);
|
||||||
|
promise.resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void createChannels(ReadableArray channelsArray, Promise promise) {
|
||||||
|
notificationManager.createChannels(channelsArray);
|
||||||
|
promise.resolve(null);
|
||||||
|
}
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// End Android specific methods
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Start ActivityEventListener methods
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
|
||||||
|
// FCM functionality does not need this function
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNewIntent(Intent intent) {
|
||||||
|
WritableMap notificationOpenedMap = parseIntentForRemoteNotification(intent);
|
||||||
|
if (notificationOpenedMap != null) {
|
||||||
|
Log.d(TAG, "onNewIntent called with new remote notification");
|
||||||
|
Utils.sendEvent(getReactApplicationContext(), "notifications_notification_opened", notificationOpenedMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// End ActivityEventListener methods
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Start LifecycleEventListener methods
|
// Start LifecycleEventListener methods
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
@ -109,10 +204,102 @@ public class RNFirebaseNotifications extends ReactContextBaseJavaModule implemen
|
||||||
// End LifecycleEventListener methods
|
// End LifecycleEventListener methods
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
private WritableMap parseIntentForRemoteNotification(Intent intent) {
|
||||||
|
// Check if FCM data exists
|
||||||
|
if (intent.getExtras() == null || !intent.hasExtra("google.message_id")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bundle extras = intent.getExtras();
|
||||||
|
|
||||||
|
WritableMap notificationMap = Arguments.createMap();
|
||||||
|
WritableMap dataMap = Arguments.createMap();
|
||||||
|
|
||||||
|
for (String key : extras.keySet()) {
|
||||||
|
if (key.equals("google.message_id")) {
|
||||||
|
notificationMap.putString("notificationId", extras.getString(key));
|
||||||
|
} else if (key.equals("collapse_key")
|
||||||
|
|| key.equals("from")
|
||||||
|
|| key.equals("google.sent_time")
|
||||||
|
|| key.equals("google.ttl")
|
||||||
|
|| key.equals("_fbSourceApplicationHasBeenSet")) {
|
||||||
|
// ignore known unneeded fields
|
||||||
|
} else {
|
||||||
|
dataMap.putString(key, extras.getString(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notificationMap.putMap("data", dataMap);
|
||||||
|
|
||||||
|
WritableMap notificationOpenedMap = Arguments.createMap();
|
||||||
|
notificationOpenedMap.putString("action", intent.getAction());
|
||||||
|
notificationOpenedMap.putMap("notification", notificationMap);
|
||||||
|
|
||||||
|
return notificationOpenedMap;
|
||||||
|
}
|
||||||
|
|
||||||
private WritableMap parseNotificationBundle(Bundle notification) {
|
private WritableMap parseNotificationBundle(Bundle notification) {
|
||||||
return Arguments.makeNativeMap(notification);
|
return Arguments.makeNativeMap(notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WritableMap parseRemoteMessage(RemoteMessage message) {
|
||||||
|
RemoteMessage.Notification notification = message.getNotification();
|
||||||
|
|
||||||
|
WritableMap notificationMap = Arguments.createMap();
|
||||||
|
WritableMap dataMap = Arguments.createMap();
|
||||||
|
|
||||||
|
// Cross platform notification properties
|
||||||
|
notificationMap.putString("body", notification.getBody());
|
||||||
|
if (message.getData() != null) {
|
||||||
|
for (Map.Entry<String, String> e : message.getData().entrySet()) {
|
||||||
|
dataMap.putString(e.getKey(), e.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notificationMap.putMap("data", dataMap);
|
||||||
|
if (message.getMessageId() != null) {
|
||||||
|
notificationMap.putString("notificationId", message.getMessageId());
|
||||||
|
}
|
||||||
|
if (notification.getSound() != null) {
|
||||||
|
notificationMap.putString("sound", notification.getSound());
|
||||||
|
}
|
||||||
|
if (notification.getTitle() != null) {
|
||||||
|
notificationMap.putString("title", notification.getTitle());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Android specific notification properties
|
||||||
|
WritableMap androidMap = Arguments.createMap();
|
||||||
|
if (notification.getClickAction() != null) {
|
||||||
|
androidMap.putString("clickAction", notification.getClickAction());
|
||||||
|
}
|
||||||
|
if (notification.getColor() != null) {
|
||||||
|
androidMap.putString("color", notification.getColor());
|
||||||
|
}
|
||||||
|
if (notification.getIcon() != null) {
|
||||||
|
WritableMap iconMap = Arguments.createMap();
|
||||||
|
iconMap.putString("icon", notification.getIcon());
|
||||||
|
androidMap.putMap("smallIcon", iconMap);
|
||||||
|
}
|
||||||
|
if (notification.getTag() != null) {
|
||||||
|
androidMap.putString("group", notification.getTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
return notificationMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RemoteNotificationReceiver extends BroadcastReceiver {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (getReactApplicationContext().hasActiveCatalystInstance()) {
|
||||||
|
Log.d(TAG, "Received new remote notification");
|
||||||
|
|
||||||
|
RemoteMessage message = intent.getParcelableExtra("notification");
|
||||||
|
WritableMap messageMap = parseRemoteMessage(message);
|
||||||
|
|
||||||
|
Utils.sendEvent(getReactApplicationContext(), "notifications_notification_received", messageMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class ScheduledNotificationReceiver extends BroadcastReceiver {
|
private class ScheduledNotificationReceiver extends BroadcastReceiver {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ export default class RemoteMessage {
|
||||||
this._data = inboundMessage.data;
|
this._data = inboundMessage.data;
|
||||||
this._from = inboundMessage.from;
|
this._from = inboundMessage.from;
|
||||||
this._messageId = inboundMessage.messageId;
|
this._messageId = inboundMessage.messageId;
|
||||||
|
this._messageType = inboundMessage.messageType;
|
||||||
this._sentTime = inboundMessage.sentTime;
|
this._sentTime = inboundMessage.sentTime;
|
||||||
}
|
}
|
||||||
// defaults
|
// defaults
|
||||||
|
@ -50,6 +51,10 @@ export default class RemoteMessage {
|
||||||
return this._messageId;
|
return this._messageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get messageType(): ?string {
|
||||||
|
return this._messageType;
|
||||||
|
}
|
||||||
|
|
||||||
get sentTime(): ?number {
|
get sentTime(): ?number {
|
||||||
return this._sentTime;
|
return this._sentTime;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ export type NativeInboundRemoteMessage = {
|
||||||
data: { [string]: string },
|
data: { [string]: string },
|
||||||
from?: string,
|
from?: string,
|
||||||
messageId: string,
|
messageId: string,
|
||||||
|
messageType?: string,
|
||||||
sentTime?: number,
|
sentTime?: number,
|
||||||
to?: string,
|
to?: string,
|
||||||
ttl?: number,
|
ttl?: number,
|
||||||
|
|
|
@ -0,0 +1,213 @@
|
||||||
|
/**
|
||||||
|
* @flow
|
||||||
|
* AndroidChannel representation wrapper
|
||||||
|
*/
|
||||||
|
import type { ImportanceType, VisibilityType } from './types';
|
||||||
|
|
||||||
|
type NativeAndroidChannel = {|
|
||||||
|
bypassDnd?: boolean,
|
||||||
|
channelId: string,
|
||||||
|
description?: string,
|
||||||
|
group?: string,
|
||||||
|
importance: ImportanceType,
|
||||||
|
lightColor?: string,
|
||||||
|
lockScreenVisibility?: VisibilityType,
|
||||||
|
name: string,
|
||||||
|
showBadge?: boolean,
|
||||||
|
sound?: string,
|
||||||
|
vibrationPattern?: number[],
|
||||||
|
|};
|
||||||
|
|
||||||
|
export default class AndroidChannel {
|
||||||
|
_bypassDnd: boolean | void;
|
||||||
|
_channelId: string;
|
||||||
|
_description: string | void;
|
||||||
|
_group: string | void;
|
||||||
|
_importance: ImportanceType;
|
||||||
|
_lightColor: string | void;
|
||||||
|
_lockScreenVisibility: VisibilityType;
|
||||||
|
_name: string;
|
||||||
|
_showBadge: boolean | void;
|
||||||
|
_sound: string | void;
|
||||||
|
_vibrationPattern: number[] | void;
|
||||||
|
|
||||||
|
get bypassDnd(): ?boolean {
|
||||||
|
return this._bypassDnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
get channelId(): string {
|
||||||
|
return this._channelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
get description(): ?string {
|
||||||
|
return this._description;
|
||||||
|
}
|
||||||
|
|
||||||
|
get group(): ?string {
|
||||||
|
return this._group;
|
||||||
|
}
|
||||||
|
|
||||||
|
get importance(): ImportanceType {
|
||||||
|
return this._importance;
|
||||||
|
}
|
||||||
|
|
||||||
|
get lightColor(): ?string {
|
||||||
|
return this._lightColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
get lockScreenVisibility(): ?VisibilityType {
|
||||||
|
return this._lockScreenVisibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
get name(): string {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
|
||||||
|
get showBadge(): ?boolean {
|
||||||
|
return this._showBadge;
|
||||||
|
}
|
||||||
|
|
||||||
|
get sound(): ?string {
|
||||||
|
return this._sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
get vibrationPattern(): ?(number[]) {
|
||||||
|
return this._vibrationPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param bypassDnd
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setBypassDnd(bypassDnd: boolean): AndroidChannel {
|
||||||
|
this._bypassDnd = bypassDnd;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param channelId
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setChannelId(channelId: string): AndroidChannel {
|
||||||
|
this._channelId = channelId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param description
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setDescription(description: string): AndroidChannel {
|
||||||
|
this._description = description;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param group
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setGroup(groupId: string): AndroidChannel {
|
||||||
|
this._group = groupId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param importance
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setImportance(importance: ImportanceType): AndroidChannel {
|
||||||
|
this._importance = importance;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param lightColor
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setLightColor(lightColor: string): AndroidChannel {
|
||||||
|
this._lightColor = lightColor;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param lockScreenVisibility
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setLockScreenVisibility(
|
||||||
|
lockScreenVisibility: VisibilityType
|
||||||
|
): AndroidChannel {
|
||||||
|
this._lockScreenVisibility = lockScreenVisibility;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setName(name: string): AndroidChannel {
|
||||||
|
this._name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param showBadge
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setShowBadge(showBadge: boolean): AndroidChannel {
|
||||||
|
this._showBadge = showBadge;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param sound
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setSound(sound: string): AndroidChannel {
|
||||||
|
this._sound = sound;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param vibrationPattern
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setVibrationPattern(vibrationPattern: number[]): AndroidChannel {
|
||||||
|
this._vibrationPattern = vibrationPattern;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
build(): NativeAndroidChannel {
|
||||||
|
if (!this._channelId) {
|
||||||
|
throw new Error('AndroidChannel: Missing required `channelId` property');
|
||||||
|
} else if (!this._importance) {
|
||||||
|
throw new Error('AndroidChannel: Missing required `importance` property');
|
||||||
|
} else if (!this._name) {
|
||||||
|
throw new Error('AndroidChannel: Missing required `name` property');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
bypassDnd: this._bypassDnd,
|
||||||
|
channelId: this._channelId,
|
||||||
|
description: this._description,
|
||||||
|
group: this._group,
|
||||||
|
importance: this._importance,
|
||||||
|
lightColor: this._lightColor,
|
||||||
|
lockScreenVisibility: this._lockScreenVisibility,
|
||||||
|
name: this._name,
|
||||||
|
showBadge: this._showBadge,
|
||||||
|
sound: this._sound,
|
||||||
|
vibrationPattern: this._vibrationPattern,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/**
|
||||||
|
* @flow
|
||||||
|
* AndroidChannelGroup representation wrapper
|
||||||
|
*/
|
||||||
|
|
||||||
|
type NativeAndroidChannelGroup = {|
|
||||||
|
groupId: string,
|
||||||
|
name: string,
|
||||||
|
|};
|
||||||
|
|
||||||
|
export default class AndroidChannel {
|
||||||
|
_groupId: string;
|
||||||
|
_name: string;
|
||||||
|
|
||||||
|
get groupId(): string {
|
||||||
|
return this._groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
get name(): string {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param groupId
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setGroupId(groupId: string): AndroidChannel {
|
||||||
|
this._groupId = groupId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @returns {AndroidChannel}
|
||||||
|
*/
|
||||||
|
setName(name: string): AndroidChannel {
|
||||||
|
this._name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
build(): NativeAndroidChannelGroup {
|
||||||
|
if (!this._groupId) {
|
||||||
|
throw new Error(
|
||||||
|
'AndroidChannelGroup: Missing required `groupId` property'
|
||||||
|
);
|
||||||
|
} else if (!this._name) {
|
||||||
|
throw new Error('AndroidChannelGroup: Missing required `name` property');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
groupId: this._groupId,
|
||||||
|
name: this._name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
/**
|
||||||
|
* @flow
|
||||||
|
* AndroidNotifications representation wrapper
|
||||||
|
*/
|
||||||
|
import { Platform } from 'react-native';
|
||||||
|
import AndroidChannel from './AndroidChannel';
|
||||||
|
import AndroidChannelGroup from './AndroidChannelGroup';
|
||||||
|
import { getNativeModule } from '../../utils/native';
|
||||||
|
|
||||||
|
import type Notifications from './';
|
||||||
|
|
||||||
|
export default class AndroidNotifications {
|
||||||
|
_notifications: Notifications;
|
||||||
|
|
||||||
|
constructor(notifications: Notifications) {
|
||||||
|
this._notifications = notifications;
|
||||||
|
}
|
||||||
|
|
||||||
|
createChannel(channel: AndroidChannel): Promise<void> {
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
if (!(channel instanceof AndroidChannel)) {
|
||||||
|
throw new Error(
|
||||||
|
`AndroidNotifications:createChannel expects an 'AndroidChannel' but got type ${typeof channel}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return getNativeModule(this._notifications).createChannel(
|
||||||
|
channel.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
createChannelGroup(channelGroup: AndroidChannelGroup): Promise<void> {
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
if (!(channelGroup instanceof AndroidChannelGroup)) {
|
||||||
|
throw new Error(
|
||||||
|
`AndroidNotifications:createChannelGroup expects an 'AndroidChannelGroup' but got type ${typeof channelGroup}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return getNativeModule(this._notifications).createChannelGroup(
|
||||||
|
channelGroup.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
createChannelGroups(channelGroups: AndroidChannelGroup[]): Promise<void> {
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
if (!Array.isArray(channelGroups)) {
|
||||||
|
throw new Error(
|
||||||
|
`AndroidNotifications:createChannelGroups expects an 'Array' but got type ${typeof channelGroups}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const nativeChannelGroups = [];
|
||||||
|
for (let i = 0; i < channelGroups.length; i++) {
|
||||||
|
const channelGroup = channelGroups[i];
|
||||||
|
if (!(channelGroup instanceof AndroidChannelGroup)) {
|
||||||
|
throw new Error(
|
||||||
|
`AndroidNotifications:createChannelGroups expects array items of type 'AndroidChannelGroup' but got type ${typeof channelGroup}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
nativeChannelGroups.push(channelGroup.build());
|
||||||
|
}
|
||||||
|
return getNativeModule(this._notifications).createChannelGroups(
|
||||||
|
nativeChannelGroups
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
createChannels(channels: AndroidChannel[]): Promise<void> {
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
if (!Array.isArray(channels)) {
|
||||||
|
throw new Error(
|
||||||
|
`AndroidNotifications:createChannels expects an 'Array' but got type ${typeof channels}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const nativeChannels = [];
|
||||||
|
for (let i = 0; i < channels.length; i++) {
|
||||||
|
const channel = channels[i];
|
||||||
|
if (!(channel instanceof AndroidChannel)) {
|
||||||
|
throw new Error(
|
||||||
|
`AndroidNotifications:createChannels expects array items of type 'AndroidChannel' but got type ${typeof channel}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
nativeChannels.push(channel.build());
|
||||||
|
}
|
||||||
|
return getNativeModule(this._notifications).createChannels(
|
||||||
|
nativeChannels
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +1,22 @@
|
||||||
/**
|
/**
|
||||||
* @flow
|
* @flow
|
||||||
* Messaging (FCM) representation wrapper
|
* Notifications representation wrapper
|
||||||
*/
|
*/
|
||||||
import { SharedEventEmitter } from '../../utils/events';
|
import { SharedEventEmitter } from '../../utils/events';
|
||||||
import { getLogger } from '../../utils/log';
|
import { getLogger } from '../../utils/log';
|
||||||
import ModuleBase from '../../utils/ModuleBase';
|
import ModuleBase from '../../utils/ModuleBase';
|
||||||
import { getNativeModule } from '../../utils/native';
|
import { getNativeModule } from '../../utils/native';
|
||||||
import { isFunction, isObject } from '../../utils';
|
import { isFunction, isObject } from '../../utils';
|
||||||
|
import AndroidChannel from './AndroidChannel';
|
||||||
|
import AndroidChannelGroup from './AndroidChannelGroup';
|
||||||
|
import AndroidNotifications from './AndroidNotifications';
|
||||||
import Notification from './Notification';
|
import Notification from './Notification';
|
||||||
import {
|
import {
|
||||||
BadgeIconType,
|
BadgeIconType,
|
||||||
Category,
|
Category,
|
||||||
Defaults,
|
Defaults,
|
||||||
GroupAlert,
|
GroupAlert,
|
||||||
|
Importance,
|
||||||
Priority,
|
Priority,
|
||||||
Visibility,
|
Visibility,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
@ -64,6 +68,8 @@ export const NAMESPACE = 'notifications';
|
||||||
* @class Notifications
|
* @class Notifications
|
||||||
*/
|
*/
|
||||||
export default class Notifications extends ModuleBase {
|
export default class Notifications extends ModuleBase {
|
||||||
|
_android: AndroidNotifications;
|
||||||
|
|
||||||
constructor(app: App) {
|
constructor(app: App) {
|
||||||
super(app, {
|
super(app, {
|
||||||
events: NATIVE_EVENTS,
|
events: NATIVE_EVENTS,
|
||||||
|
@ -71,6 +77,7 @@ export default class Notifications extends ModuleBase {
|
||||||
multiApp: false,
|
multiApp: false,
|
||||||
namespace: NAMESPACE,
|
namespace: NAMESPACE,
|
||||||
});
|
});
|
||||||
|
this._android = new AndroidNotifications(this);
|
||||||
|
|
||||||
SharedEventEmitter.addListener(
|
SharedEventEmitter.addListener(
|
||||||
// sub to internal native event - this fans out to
|
// sub to internal native event - this fans out to
|
||||||
|
@ -89,7 +96,7 @@ export default class Notifications extends ModuleBase {
|
||||||
// public event name: onNotificationOpened
|
// public event name: onNotificationOpened
|
||||||
'notifications_notification_opened',
|
'notifications_notification_opened',
|
||||||
(notificationOpened: NativeNotificationOpened) => {
|
(notificationOpened: NativeNotificationOpened) => {
|
||||||
SharedEventEmitter.emit('OnNotificationOpened', {
|
SharedEventEmitter.emit('onNotificationOpened', {
|
||||||
action: notificationOpened.action,
|
action: notificationOpened.action,
|
||||||
notification: new Notification(notificationOpened.notification),
|
notification: new Notification(notificationOpened.notification),
|
||||||
});
|
});
|
||||||
|
@ -109,6 +116,10 @@ export default class Notifications extends ModuleBase {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get android(): AndroidNotifications {
|
||||||
|
return this._android;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel all notifications
|
* Cancel all notifications
|
||||||
*/
|
*/
|
||||||
|
@ -148,9 +159,11 @@ export default class Notifications extends ModuleBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
getInitialNotification(): Promise<Object> {
|
getInitialNotification(): Promise<Object> {
|
||||||
return getNativeModule(this).getInitialNotification();
|
return getNativeModule(this)
|
||||||
// TODO
|
.getInitialNotification()
|
||||||
// .then(notification => (notification ? new Notification(this, notification) : null));
|
.then(
|
||||||
|
notification => (notification ? new Notification(notification) : null)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -278,8 +291,11 @@ export const statics = {
|
||||||
Android: {
|
Android: {
|
||||||
BadgeIconType,
|
BadgeIconType,
|
||||||
Category,
|
Category,
|
||||||
|
Channel: AndroidChannel,
|
||||||
|
ChannelGroup: AndroidChannelGroup,
|
||||||
Defaults,
|
Defaults,
|
||||||
GroupAlert,
|
GroupAlert,
|
||||||
|
Importance,
|
||||||
Priority,
|
Priority,
|
||||||
Visibility,
|
Visibility,
|
||||||
},
|
},
|
||||||
|
|
|
@ -39,6 +39,16 @@ export const GroupAlert = {
|
||||||
Summary: 1,
|
Summary: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const Importance = {
|
||||||
|
Default: 3,
|
||||||
|
High: 4,
|
||||||
|
Low: 2,
|
||||||
|
Max: 5,
|
||||||
|
Min: 1,
|
||||||
|
None: 3,
|
||||||
|
Unspecified: -1000,
|
||||||
|
};
|
||||||
|
|
||||||
export const Priority = {
|
export const Priority = {
|
||||||
Default: 0,
|
Default: 0,
|
||||||
High: 1,
|
High: 1,
|
||||||
|
@ -57,6 +67,7 @@ export type BadgeIconTypeType = $Values<typeof BadgeIconType>;
|
||||||
export type CategoryType = $Values<typeof Category>;
|
export type CategoryType = $Values<typeof Category>;
|
||||||
export type DefaultsType = $Values<typeof Defaults>;
|
export type DefaultsType = $Values<typeof Defaults>;
|
||||||
export type GroupAlertType = $Values<typeof GroupAlert>;
|
export type GroupAlertType = $Values<typeof GroupAlert>;
|
||||||
|
export type ImportanceType = $Values<typeof Importance>;
|
||||||
export type PriorityType = $Values<typeof Priority>;
|
export type PriorityType = $Values<typeof Priority>;
|
||||||
export type VisibilityType = $Values<typeof Visibility>;
|
export type VisibilityType = $Values<typeof Visibility>;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import io.invertase.firebase.firestore.RNFirebaseFirestorePackage;
|
||||||
import io.invertase.firebase.instanceid.RNFirebaseInstanceIdPackage;
|
import io.invertase.firebase.instanceid.RNFirebaseInstanceIdPackage;
|
||||||
import io.invertase.firebase.links.RNFirebaseLinksPackage;
|
import io.invertase.firebase.links.RNFirebaseLinksPackage;
|
||||||
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage;
|
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage;
|
||||||
|
import io.invertase.firebase.notifications.RNFirebaseNotificationsPackage;
|
||||||
import io.invertase.firebase.perf.RNFirebasePerformancePackage;
|
import io.invertase.firebase.perf.RNFirebasePerformancePackage;
|
||||||
import io.invertase.firebase.storage.RNFirebaseStoragePackage;
|
import io.invertase.firebase.storage.RNFirebaseStoragePackage;
|
||||||
import com.oblador.vectoricons.VectorIconsPackage;
|
import com.oblador.vectoricons.VectorIconsPackage;
|
||||||
|
@ -51,6 +52,7 @@ public class MainApplication extends Application implements ReactApplication {
|
||||||
new RNFirebaseInstanceIdPackage(),
|
new RNFirebaseInstanceIdPackage(),
|
||||||
new RNFirebaseLinksPackage(),
|
new RNFirebaseLinksPackage(),
|
||||||
new RNFirebaseMessagingPackage(),
|
new RNFirebaseMessagingPackage(),
|
||||||
|
new RNFirebaseNotificationsPackage(),
|
||||||
new RNFirebasePerformancePackage(),
|
new RNFirebasePerformancePackage(),
|
||||||
new RNFirebaseStoragePackage()
|
new RNFirebaseStoragePackage()
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,14 +7,6 @@ import DatabaseContents from './tests/support/DatabaseContents';
|
||||||
RNfirebase.database.enableLogging(true);
|
RNfirebase.database.enableLogging(true);
|
||||||
RNfirebase.firestore.enableLogging(true);
|
RNfirebase.firestore.enableLogging(true);
|
||||||
|
|
||||||
RNfirebase.messaging().onMessage(message => {
|
|
||||||
console.log('got new message: ', message);
|
|
||||||
});
|
|
||||||
|
|
||||||
RNfirebase.messaging().onTokenRefresh(token => {
|
|
||||||
console.log('got new token: ', token);
|
|
||||||
});
|
|
||||||
|
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
try {
|
try {
|
||||||
await RNfirebase.messaging().requestPermission();
|
await RNfirebase.messaging().requestPermission();
|
||||||
|
@ -22,9 +14,47 @@ const init = async () => {
|
||||||
console.log('instanceid: ', instanceid);
|
console.log('instanceid: ', instanceid);
|
||||||
const token = await RNfirebase.messaging().getToken();
|
const token = await RNfirebase.messaging().getToken();
|
||||||
console.log('token: ', token);
|
console.log('token: ', token);
|
||||||
const initialMessage = await RNfirebase.messaging().getInitialMessage();
|
const initialNotification = await RNfirebase.notifications().getInitialNotification();
|
||||||
console.log('initial message: ', initialMessage);
|
console.log('initialNotification: ', initialNotification);
|
||||||
|
|
||||||
|
RNfirebase.messaging().onMessage(message => {
|
||||||
|
console.log('onMessage: ', message);
|
||||||
|
});
|
||||||
|
RNfirebase.messaging().onTokenRefresh(deviceToken => {
|
||||||
|
dispatch(fcmTokenReceived(deviceToken));
|
||||||
|
});
|
||||||
|
RNfirebase.notifications().onNotification(notification => {
|
||||||
|
console.log('onNotification: ', notification);
|
||||||
|
});
|
||||||
|
RNfirebase.notifications().onNotificationOpened(notification => {
|
||||||
|
console.log('onNotificationOpened: ', notification);
|
||||||
|
});
|
||||||
|
RNfirebase.notifications().onNotificationDisplayed(notification => {
|
||||||
|
console.log('onNotificationDisplayed: ', notification);
|
||||||
|
});
|
||||||
// RNfirebase.instanceid().delete();
|
// RNfirebase.instanceid().delete();
|
||||||
|
const channel = new RNfirebase.notifications.Android.Channel();
|
||||||
|
channel
|
||||||
|
.setChannelId('test')
|
||||||
|
.setName('test')
|
||||||
|
.setImportance(RNfirebase.notifications.Android.Importance.Max)
|
||||||
|
.setDescription('test channel');
|
||||||
|
RNfirebase.notifications().android.createChannel(channel);
|
||||||
|
|
||||||
|
const notification = new RNfirebase.notifications.Notification();
|
||||||
|
notification
|
||||||
|
.setTitle('Test title')
|
||||||
|
.setBody('Test body')
|
||||||
|
.android.setChannelId('test')
|
||||||
|
.android.setPriority(RNfirebase.notifications.Android.Priority.Max);
|
||||||
|
const date = new Date();
|
||||||
|
date.setMinutes(date.getMinutes() + 1);
|
||||||
|
setTimeout(() => {
|
||||||
|
RNfirebase.notifications().displayNotification(notification);
|
||||||
|
}, 5);
|
||||||
|
RNfirebase.notifications().scheduleNotification(notification, {
|
||||||
|
fireDate: date.getTime(),
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('messaging init error:', error);
|
console.error('messaging init error:', error);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue