[fcm] Android instanceid and core fcm support; iOS instance and basic fcm support

This commit is contained in:
Chris Bianca 2018-02-02 08:40:48 +00:00
parent d429db7e86
commit 850f04914f
28 changed files with 824 additions and 1411 deletions

View File

@ -82,7 +82,7 @@ rootProject.gradle.buildFinished { buildResult ->
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile "com.facebook.react:react-native:+" // From node_modules
compile 'me.leolin:ShortcutBadger:1.1.18@aar'
compile 'me.leolin:ShortcutBadger:1.1.21@aar'
compile "com.google.android.gms:play-services-base:$firebaseVersion"
compile "com.google.firebase:firebase-core:$firebaseVersion"
compile "com.google.firebase:firebase-config:$firebaseVersion"

View File

@ -0,0 +1,45 @@
package io.invertase.firebase.instanceid;
import android.util.Log;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.google.firebase.iid.FirebaseInstanceId;
import java.io.IOException;
public class RNFirebaseInstanceId extends ReactContextBaseJavaModule {
private static final String TAG = "RNFirebaseInstanceId";
public RNFirebaseInstanceId(ReactApplicationContext reactContext) {
super(reactContext);
Log.d(TAG, "New instance");
}
@Override
public String getName() {
return TAG;
}
@ReactMethod
public void delete(Promise promise){
try {
Log.d(TAG, "Deleting instance id");
FirebaseInstanceId.getInstance().deleteInstanceId();
promise.resolve(null);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
promise.reject("instance_id_error", e.getMessage());
}
}
@ReactMethod
public void get(Promise promise){
String id = FirebaseInstanceId.getInstance().getId();
promise.resolve(id);
}
}

View File

@ -0,0 +1,38 @@
package io.invertase.firebase.instanceid;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@SuppressWarnings("unused")
public class RNFirebaseInstanceIdPackage implements ReactPackage {
public RNFirebaseInstanceIdPackage() {
}
/**
* @param reactContext react application context that can be used to create modules
* @return list of native modules to register with the newly created catalyst instance
*/
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new RNFirebaseInstanceId(reactContext));
return modules;
}
/**
* @param reactContext
* @return a list of view managers that should be registered with {@link UIManagerModule}
*/
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}

View File

@ -1,43 +0,0 @@
package io.invertase.firebase.messaging;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import me.leolin.shortcutbadger.ShortcutBadger;
public class BadgeHelper {
private static final String TAG = "BadgeHelper";
private static final String PREFERENCES_FILE = "BadgeCountFile";
private static final String BADGE_COUNT_KEY = "BadgeCount";
private Context mContext;
private SharedPreferences sharedPreferences = null;
public BadgeHelper(Context context) {
mContext = context;
sharedPreferences = (SharedPreferences) mContext.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
}
public int getBadgeCount() {
return sharedPreferences.getInt(BADGE_COUNT_KEY, 0);
}
public void setBadgeCount(int badgeCount) {
storeBadgeCount(badgeCount);
if (badgeCount == 0) {
ShortcutBadger.removeCount(mContext);
Log.d(TAG, "Remove count");
} else {
ShortcutBadger.applyCount(mContext, badgeCount);
Log.d(TAG, "Apply count: " + badgeCount);
}
}
private void storeBadgeCount(int badgeCount) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt(BADGE_COUNT_KEY, badgeCount);
editor.apply();
}
}

View File

@ -1,32 +0,0 @@
package io.invertase.firebase.messaging;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
public class InstanceIdService extends FirebaseInstanceIdService {
private static final String TAG = "InstanceIdService";
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. This call is initiated by the
* InstanceID provider.
*/
@Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
// Broadcast refreshed token
Intent i = new Intent("io.invertase.firebase.messaging.FCMRefreshToken");
Bundle bundle = new Bundle();
bundle.putString("token", refreshedToken);
i.putExtras(bundle);
sendBroadcast(i);
}
}

View File

@ -1,64 +0,0 @@
package io.invertase.firebase.messaging;
import java.util.Map;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import org.json.JSONException;
import org.json.JSONObject;
public class MessagingService extends FirebaseMessagingService {
private static final String TAG = "MessagingService";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "Remote message received");
Intent i = new Intent("io.invertase.firebase.messaging.ReceiveNotification");
i.putExtra("data", remoteMessage);
handleBadge(remoteMessage);
buildLocalNotification(remoteMessage);
sendOrderedBroadcast(i, null);
}
private void handleBadge(RemoteMessage remoteMessage) {
BadgeHelper badgeHelper = new BadgeHelper(this);
if (remoteMessage.getData() == null) {
return;
}
Map data = remoteMessage.getData();
if (data.get("badge") == null) {
return;
}
try {
int badgeCount = Integer.parseInt((String)data.get("badge"));
badgeHelper.setBadgeCount(badgeCount);
} catch (Exception e) {
Log.e(TAG, "Badge count needs to be an integer", e);
}
}
private void buildLocalNotification(RemoteMessage remoteMessage) {
if(remoteMessage.getData() == null){
return;
}
Map<String, String> data = remoteMessage.getData();
String customNotification = data.get("custom_notification");
if(customNotification != null){
try {
Bundle bundle = BundleJSONConverter.convertToBundle(new JSONObject(customNotification));
RNFirebaseLocalMessagingHelper helper = new RNFirebaseLocalMessagingHelper(this.getApplication());
helper.sendNotification(bundle);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,24 @@
package io.invertase.firebase.messaging;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.google.firebase.iid.FirebaseInstanceIdService;
public class RNFirebaseInstanceIdService extends FirebaseInstanceIdService {
private static final String TAG = "RNFInstanceIdService";
public static final String TOKEN_REFRESH_EVENT = "messaging-token-refresh";
@Override
public void onTokenRefresh() {
Log.d(TAG, "onTokenRefresh event received");
// Build an Intent to pass the token to the RN Application
Intent tokenRefreshEvent = new Intent(TOKEN_REFRESH_EVENT);
// Broadcast it so it is only available to the RN Application
LocalBroadcastManager.getInstance(this).sendBroadcast(tokenRefreshEvent);
}
}

View File

@ -1,17 +1,17 @@
package io.invertase.firebase.messaging;
import android.app.Activity;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
@ -26,26 +26,33 @@ import com.google.firebase.messaging.RemoteMessage;
import com.google.firebase.messaging.RemoteMessage.Notification;
import io.invertase.firebase.Utils;
import me.leolin.shortcutbadger.ShortcutBadger;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements LifecycleEventListener, ActivityEventListener {
private final static String TAG = RNFirebaseMessaging.class.getCanonicalName();
private RNFirebaseLocalMessagingHelper mRNFirebaseLocalMessagingHelper;
private BadgeHelper mBadgeHelper;
public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements ActivityEventListener {
private static final String BADGE_FILE = "BadgeCountFile";
private static final String BADGE_KEY = "BadgeCount";
public RNFirebaseMessaging(ReactApplicationContext reactContext) {
super(reactContext);
mRNFirebaseLocalMessagingHelper = new RNFirebaseLocalMessagingHelper((Application) reactContext.getApplicationContext());
mBadgeHelper = new BadgeHelper(reactContext.getApplicationContext());
getReactApplicationContext().addLifecycleEventListener(this);
getReactApplicationContext().addActivityEventListener(this);
registerTokenRefreshHandler();
registerMessageHandler();
registerLocalMessageHandler();
private static final String TAG = RNFirebaseMessaging.class.getCanonicalName();
private SharedPreferences sharedPreferences = null;
public RNFirebaseMessaging(ReactApplicationContext context) {
super(context);
context.addActivityEventListener(this);
sharedPreferences = context.getSharedPreferences(BADGE_FILE, Context.MODE_PRIVATE);
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
// Subscribe to message events
localBroadcastManager.registerReceiver(new MessageReceiver(),
new IntentFilter(RNFirebaseMessagingService.MESSAGE_EVENT));
// Subscribe to token refresh events
localBroadcastManager.registerReceiver(new RefreshTokenReceiver(),
new IntentFilter(RNFirebaseInstanceIdService.TOKEN_REFRESH_EVENT));
}
@Override
@ -54,73 +61,84 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements L
}
@ReactMethod
public void getInitialNotification(Promise promise) {
Activity activity = getCurrentActivity();
if (activity == null) {
public void getToken(Promise promise) {
String token = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Firebase token: " + token);
promise.resolve(token);
}
@ReactMethod
public void requestPermission(Promise promise) {
// TODO: Object structure?
promise.resolve(null);
}
// 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
public void sendMessage(ReadableMap messageMap, Promise promise) {
if (!messageMap.hasKey("to")) {
promise.reject("messaging/invalid-message", "The supplied message is missing a 'to' field");
return;
}
promise.resolve(parseIntent(getCurrentActivity().getIntent()));
}
@ReactMethod
public void requestPermissions() {
}
RemoteMessage.Builder mb = new RemoteMessage.Builder(messageMap.getString("to"));
@ReactMethod
public void getToken(Promise promise) {
Log.d(TAG, "Firebase token: " + FirebaseInstanceId.getInstance().getToken());
promise.resolve(FirebaseInstanceId.getInstance().getToken());
}
@ReactMethod
public void deleteInstanceId(Promise promise){
try {
Log.d(TAG, "Deleting instance id");
FirebaseInstanceId.getInstance().deleteInstanceId();
promise.resolve(null);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
promise.reject(null, e.getMessage());
if (messageMap.hasKey("collapseKey")) {
mb = mb.setCollapseKey(messageMap.getString("collapseKey"));
}
}
@ReactMethod
public void createLocalNotification(ReadableMap details) {
Bundle bundle = Arguments.toBundle(details);
mRNFirebaseLocalMessagingHelper.sendNotification(bundle);
}
@ReactMethod
public void scheduleLocalNotification(ReadableMap details) {
Bundle bundle = Arguments.toBundle(details);
mRNFirebaseLocalMessagingHelper.sendNotificationScheduled(bundle);
}
@ReactMethod
public void cancelLocalNotification(String notificationID) {
mRNFirebaseLocalMessagingHelper.cancelLocalNotification(notificationID);
}
@ReactMethod
public void cancelAllLocalNotifications() {
try {
mRNFirebaseLocalMessagingHelper.cancelAllLocalNotifications();
} catch (SecurityException e) {
// In some devices/situations cancelAllLocalNotifications will throw a SecurityException
// We can safely ignore this error for now as the UX impact of this not working is minor.
Log.w(TAG, e.getMessage());
if (messageMap.hasKey("messageId")) {
mb = mb.setMessageId(messageMap.getString("messageId"));
}
if (messageMap.hasKey("messageType")) {
mb = mb.setMessageType(messageMap.getString("messageType"));
}
if (messageMap.hasKey("ttl")) {
mb = mb.setTtl(messageMap.getInt("ttl"));
}
if (messageMap.hasKey("data")) {
ReadableMap dataMap = messageMap.getMap("data");
ReadableMapKeySetIterator iterator = dataMap.keySetIterator();
while (iterator.hasNextKey()) {
String key = iterator.nextKey();
mb = mb.addData(key, dataMap.getString(key));
}
}
FirebaseMessaging.getInstance().send(mb.build());
// TODO: Listen to onMessageSent and onSendError for better feedback?
promise.resolve(null);
}
@ReactMethod
public void removeDeliveredNotification(String notificationID) {
mRNFirebaseLocalMessagingHelper.removeDeliveredNotification(notificationID);
}
@ReactMethod
public void removeAllDeliveredNotifications() {
mRNFirebaseLocalMessagingHelper.removeAllDeliveredNotifications();
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
@ -133,159 +151,163 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements L
FirebaseMessaging.getInstance().unsubscribeFromTopic(topic);
}
@ReactMethod
public void getScheduledLocalNotifications(Promise promise) {
ArrayList<Bundle> bundles = mRNFirebaseLocalMessagingHelper.getScheduledLocalNotifications();
WritableArray array = Arguments.createArray();
for (Bundle bundle : bundles) {
array.pushMap(Arguments.fromBundle(bundle));
}
promise.resolve(array);
}
@ReactMethod
public void setBadgeNumber(int badgeNumber) {
mBadgeHelper.setBadgeCount(badgeNumber);
}
@ReactMethod
public void getBadgeNumber(Promise promise) {
promise.resolve(mBadgeHelper.getBadgeCount());
}
private void registerTokenRefreshHandler() {
IntentFilter intentFilter = new IntentFilter("io.invertase.firebase.messaging.FCMRefreshToken");
getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (getReactApplicationContext().hasActiveCatalystInstance()) {
String token = intent.getStringExtra("token");
Utils.sendEvent(getReactApplicationContext(), "messaging_token_refreshed", token);
}
}
}, intentFilter);
}
@ReactMethod
public void send(ReadableMap remoteMessage) {
FirebaseMessaging fm = FirebaseMessaging.getInstance();
RemoteMessage.Builder message = new RemoteMessage.Builder(remoteMessage.getString("sender"));
message.setTtl(remoteMessage.getInt("ttl"));
message.setMessageId(remoteMessage.getString("id"));
message.setMessageType(remoteMessage.getString("type"));
if (remoteMessage.hasKey("collapseKey")) {
message.setCollapseKey(remoteMessage.getString("collapseKey"));
}
// get data keys and values and add to builder
// js side ensures all data values are strings
// so no need to check types
ReadableMap data = remoteMessage.getMap("data");
ReadableMapKeySetIterator iterator = data.keySetIterator();
while (iterator.hasNextKey()) {
String key = iterator.nextKey();
String value = data.getString(key);
message.addData(key, value);
}
fm.send(message.build());
}
private void registerMessageHandler() {
IntentFilter intentFilter = new IntentFilter("io.invertase.firebase.messaging.ReceiveNotification");
getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (getReactApplicationContext().hasActiveCatalystInstance()) {
RemoteMessage message = intent.getParcelableExtra("data");
WritableMap params = Arguments.createMap();
WritableMap fcmData = Arguments.createMap();
if (message.getNotification() != null) {
Notification notification = message.getNotification();
fcmData.putString("title", notification.getTitle());
fcmData.putString("body", notification.getBody());
fcmData.putString("color", notification.getColor());
fcmData.putString("icon", notification.getIcon());
fcmData.putString("tag", notification.getTag());
fcmData.putString("action", notification.getClickAction());
}
params.putMap("fcm", fcmData);
if (message.getData() != null) {
Map<String, String> data = message.getData();
Set<String> keysIterator = data.keySet();
for (String key : keysIterator) {
params.putString(key, data.get(key));
}
}
Utils.sendEvent(getReactApplicationContext(), "messaging_notification_received", params);
}
}
}, intentFilter);
}
private void registerLocalMessageHandler() {
IntentFilter intentFilter = new IntentFilter("io.invertase.firebase.messaging.ReceiveLocalNotification");
getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (getReactApplicationContext().hasActiveCatalystInstance()) {
Utils.sendEvent(getReactApplicationContext(), "messaging_notification_received", Arguments.fromBundle(intent.getExtras()));
}
}
}, intentFilter);
}
private WritableMap parseIntent(Intent intent) {
WritableMap params;
Bundle extras = intent.getExtras();
if (extras != null) {
try {
params = Arguments.fromBundle(extras);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
params = Arguments.createMap();
}
} else {
params = Arguments.createMap();
}
WritableMap fcm = Arguments.createMap();
fcm.putString("action", intent.getAction());
params.putMap("fcm", fcm);
params.putBoolean("opened_from_tray", true);
return params;
}
@Override
public void onHostResume() {
mRNFirebaseLocalMessagingHelper.setApplicationForeground(true);
}
@Override
public void onHostPause() {
mRNFirebaseLocalMessagingHelper.setApplicationForeground(false);
}
@Override
public void onHostDestroy() {
}
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
// todo hmm?
// FCM functionality does not need this function
}
@Override
public void onNewIntent(Intent intent) {
// todo hmm?
Utils.sendEvent(getReactApplicationContext(), "messaging_notification_received", parseIntent(intent));
WritableMap messageMap = parseIntentForMessage(intent);
if (messageMap != null) {
Log.d(TAG, "onNewIntent called with new FCM message");
Utils.sendEvent(getReactApplicationContext(), "messaging_message_received", messageMap);
}
}
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 {
dataMap.putString(key, extras.getString(key));
}
}
messageMap.putMap("data", dataMap);
messageMap.putBoolean("openedFromTray", true);
return messageMap;
}
private class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (getReactApplicationContext().hasActiveCatalystInstance()) {
Log.d(TAG, "Received new message");
RemoteMessage message = intent.getParcelableExtra("message");
WritableMap messageMap = buildMessageMap(message);
Utils.sendEvent(getReactApplicationContext(), "messaging_message_received", messageMap);
}
}
private WritableMap buildMessageMap(RemoteMessage message) {
WritableMap messageMap = Arguments.createMap();
WritableMap dataMap = Arguments.createMap();
if (message.getCollapseKey() != null) {
messageMap.putString("collapseKey", message.getCollapseKey());
}
if (message.getData() != null) {
for (Map.Entry<String, String> e : message.getData().entrySet()) {
dataMap.putString(e.getKey(), e.getValue());
}
}
messageMap.putMap("data", dataMap);
if (message.getFrom() != null) {
messageMap.putString("from", message.getFrom());
}
if (message.getMessageId() != null) {
messageMap.putString("messageId", message.getMessageId());
}
if (message.getMessageType() != null) {
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());
if (message.getTo() != null) {
messageMap.putString("to", message.getTo());
}
messageMap.putDouble("ttl", message.getTtl());
return messageMap;
}
}
private class RefreshTokenReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (getReactApplicationContext().hasActiveCatalystInstance()) {
String token = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Received new token: " + token);
Utils.sendEvent(getReactApplicationContext(), "messaging_token_refreshed", token);
}
}
}
}

View File

@ -0,0 +1,25 @@
package io.invertase.firebase.messaging;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class RNFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "RNFMessagingService";
public static final String MESSAGE_EVENT = "messaging-message";
@Override
public void onMessageReceived(RemoteMessage message) {
Log.d(TAG, "onMessageReceived event received");
// Build an Intent to pass the token to the RN Application
Intent messageEvent = new Intent(MESSAGE_EVENT);
messageEvent.putExtra("message", message);
// Broadcast it so it is only available to the RN Application
LocalBroadcastManager.getInstance(this).sendBroadcast(messageEvent);
}
}

View File

@ -17,7 +17,9 @@
8376F7141F7C149100D45A85 /* RNFirebaseFirestoreDocumentReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 8376F70E1F7C149000D45A85 /* RNFirebaseFirestoreDocumentReference.m */; };
8376F7151F7C149100D45A85 /* RNFirebaseFirestore.m in Sources */ = {isa = PBXBuildFile; fileRef = 8376F7101F7C149000D45A85 /* RNFirebaseFirestore.m */; };
8376F7161F7C149100D45A85 /* RNFirebaseFirestoreCollectionReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 8376F7111F7C149000D45A85 /* RNFirebaseFirestoreCollectionReference.m */; };
838E36FE201B9169004DCD3A /* NewRNFirebaseMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = 838E36FD201B9169004DCD3A /* NewRNFirebaseMessaging.m */; };
838E36FE201B9169004DCD3A /* RNFirebaseMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = 838E36FD201B9169004DCD3A /* RNFirebaseMessaging.m */; };
838E372320231DF0004DCD3A /* RNFirebaseInstanceId.m in Sources */ = {isa = PBXBuildFile; fileRef = 838E372220231DF0004DCD3A /* RNFirebaseInstanceId.m */; };
838E372720231E15004DCD3A /* RNFirebaseNotifications.m in Sources */ = {isa = PBXBuildFile; fileRef = 838E372520231E15004DCD3A /* RNFirebaseNotifications.m */; };
839D916C1EF3E20B0077C7C8 /* RNFirebaseAdMob.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D914F1EF3E20A0077C7C8 /* RNFirebaseAdMob.m */; };
839D916D1EF3E20B0077C7C8 /* RNFirebaseAdMobInterstitial.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D91511EF3E20A0077C7C8 /* RNFirebaseAdMobInterstitial.m */; };
839D916E1EF3E20B0077C7C8 /* RNFirebaseAdMobRewardedVideo.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D91531EF3E20A0077C7C8 /* RNFirebaseAdMobRewardedVideo.m */; };
@ -26,7 +28,6 @@
839D91711EF3E20B0077C7C8 /* RNFirebaseRemoteConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D915C1EF3E20A0077C7C8 /* RNFirebaseRemoteConfig.m */; };
839D91721EF3E20B0077C7C8 /* RNFirebaseCrash.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D915F1EF3E20A0077C7C8 /* RNFirebaseCrash.m */; };
839D91731EF3E20B0077C7C8 /* RNFirebaseDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D91621EF3E20A0077C7C8 /* RNFirebaseDatabase.m */; };
839D91741EF3E20B0077C7C8 /* RNFirebaseMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D91651EF3E20A0077C7C8 /* RNFirebaseMessaging.m */; };
839D91751EF3E20B0077C7C8 /* RNFirebasePerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D91681EF3E20A0077C7C8 /* RNFirebasePerformance.m */; };
83C3EEEE1FA1EACC00B64D3C /* RNFirebaseUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 83C3EEEC1FA1EACC00B64D3C /* RNFirebaseUtil.m */; };
BA84AE571FA9E59800E79390 /* RNFirebaseStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = BA84AE561FA9E59800E79390 /* RNFirebaseStorage.m */; };
@ -67,8 +68,12 @@
8376F7111F7C149000D45A85 /* RNFirebaseFirestoreCollectionReference.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseFirestoreCollectionReference.m; sourceTree = "<group>"; };
8376F7121F7C149000D45A85 /* RNFirebaseFirestoreDocumentReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseFirestoreDocumentReference.h; sourceTree = "<group>"; };
8376F7131F7C149000D45A85 /* RNFirebaseFirestoreCollectionReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseFirestoreCollectionReference.h; sourceTree = "<group>"; };
838E36FC201B9169004DCD3A /* NewRNFirebaseMessaging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewRNFirebaseMessaging.h; sourceTree = "<group>"; };
838E36FD201B9169004DCD3A /* NewRNFirebaseMessaging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewRNFirebaseMessaging.m; sourceTree = "<group>"; };
838E36FC201B9169004DCD3A /* RNFirebaseMessaging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseMessaging.h; sourceTree = "<group>"; };
838E36FD201B9169004DCD3A /* RNFirebaseMessaging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseMessaging.m; sourceTree = "<group>"; };
838E372120231DF0004DCD3A /* RNFirebaseInstanceId.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseInstanceId.h; sourceTree = "<group>"; };
838E372220231DF0004DCD3A /* RNFirebaseInstanceId.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseInstanceId.m; sourceTree = "<group>"; };
838E372520231E15004DCD3A /* RNFirebaseNotifications.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseNotifications.m; sourceTree = "<group>"; };
838E372620231E15004DCD3A /* RNFirebaseNotifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseNotifications.h; sourceTree = "<group>"; };
839D914E1EF3E20A0077C7C8 /* RNFirebaseAdMob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseAdMob.h; sourceTree = "<group>"; };
839D914F1EF3E20A0077C7C8 /* RNFirebaseAdMob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseAdMob.m; sourceTree = "<group>"; };
839D91501EF3E20A0077C7C8 /* RNFirebaseAdMobInterstitial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseAdMobInterstitial.h; sourceTree = "<group>"; };
@ -85,8 +90,6 @@
839D915F1EF3E20A0077C7C8 /* RNFirebaseCrash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseCrash.m; sourceTree = "<group>"; };
839D91611EF3E20A0077C7C8 /* RNFirebaseDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseDatabase.h; sourceTree = "<group>"; };
839D91621EF3E20A0077C7C8 /* RNFirebaseDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseDatabase.m; sourceTree = "<group>"; };
839D91641EF3E20A0077C7C8 /* RNFirebaseMessaging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseMessaging.h; sourceTree = "<group>"; };
839D91651EF3E20A0077C7C8 /* RNFirebaseMessaging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseMessaging.m; sourceTree = "<group>"; };
839D91671EF3E20A0077C7C8 /* RNFirebasePerformance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebasePerformance.h; sourceTree = "<group>"; };
839D91681EF3E20A0077C7C8 /* RNFirebasePerformance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebasePerformance.m; sourceTree = "<group>"; };
839D91771EF3E22F0077C7C8 /* RNFirebaseEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNFirebaseEvents.h; path = RNFirebase/RNFirebaseEvents.h; sourceTree = "<group>"; };
@ -130,6 +133,8 @@
58B511D21A9E6C8500147676 = {
isa = PBXGroup;
children = (
838E372420231E15004DCD3A /* notifications */,
838E372020231DF0004DCD3A /* instanceid */,
8336930F1FD80DE800AA806B /* fabric */,
BA84AE541FA9E59800E79390 /* storage */,
17AF4F681F59CDBF00C02336 /* links */,
@ -182,6 +187,26 @@
path = RNFirebase/firestore;
sourceTree = "<group>";
};
838E372020231DF0004DCD3A /* instanceid */ = {
isa = PBXGroup;
children = (
838E372120231DF0004DCD3A /* RNFirebaseInstanceId.h */,
838E372220231DF0004DCD3A /* RNFirebaseInstanceId.m */,
);
name = instanceid;
path = RNFirebase/instanceid;
sourceTree = "<group>";
};
838E372420231E15004DCD3A /* notifications */ = {
isa = PBXGroup;
children = (
838E372520231E15004DCD3A /* RNFirebaseNotifications.m */,
838E372620231E15004DCD3A /* RNFirebaseNotifications.h */,
);
name = notifications;
path = RNFirebase/notifications;
sourceTree = "<group>";
};
839D914D1EF3E20A0077C7C8 /* admob */ = {
isa = PBXGroup;
children = (
@ -259,10 +284,8 @@
839D91631EF3E20A0077C7C8 /* messaging */ = {
isa = PBXGroup;
children = (
838E36FC201B9169004DCD3A /* NewRNFirebaseMessaging.h */,
838E36FD201B9169004DCD3A /* NewRNFirebaseMessaging.m */,
839D91641EF3E20A0077C7C8 /* RNFirebaseMessaging.h */,
839D91651EF3E20A0077C7C8 /* RNFirebaseMessaging.m */,
838E36FC201B9169004DCD3A /* RNFirebaseMessaging.h */,
838E36FD201B9169004DCD3A /* RNFirebaseMessaging.m */,
);
name = messaging;
path = RNFirebase/messaging;
@ -344,11 +367,12 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
838E372320231DF0004DCD3A /* RNFirebaseInstanceId.m in Sources */,
839D916E1EF3E20B0077C7C8 /* RNFirebaseAdMobRewardedVideo.m in Sources */,
839D916C1EF3E20B0077C7C8 /* RNFirebaseAdMob.m in Sources */,
17AF4F6B1F59CDBF00C02336 /* RNFirebaseLinks.m in Sources */,
8376F7161F7C149100D45A85 /* RNFirebaseFirestoreCollectionReference.m in Sources */,
838E36FE201B9169004DCD3A /* NewRNFirebaseMessaging.m in Sources */,
838E36FE201B9169004DCD3A /* RNFirebaseMessaging.m in Sources */,
8376F7151F7C149100D45A85 /* RNFirebaseFirestore.m in Sources */,
839D91701EF3E20B0077C7C8 /* RNFirebaseAuth.m in Sources */,
8323CF091F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.m in Sources */,
@ -358,11 +382,11 @@
833693131FD824EF00AA806B /* RNFirebaseCrashlytics.m in Sources */,
D950369E1D19C77400F7094D /* RNFirebase.m in Sources */,
839D91731EF3E20B0077C7C8 /* RNFirebaseDatabase.m in Sources */,
838E372720231E15004DCD3A /* RNFirebaseNotifications.m in Sources */,
BA84AE571FA9E59800E79390 /* RNFirebaseStorage.m in Sources */,
8323CF071F6FBD870071420B /* NativeExpressComponent.m in Sources */,
83C3EEEE1FA1EACC00B64D3C /* RNFirebaseUtil.m in Sources */,
839D91721EF3E20B0077C7C8 /* RNFirebaseCrash.m in Sources */,
839D91741EF3E20B0077C7C8 /* RNFirebaseMessaging.m in Sources */,
839D91751EF3E20B0077C7C8 /* RNFirebasePerformance.m in Sources */,
8323CF061F6FBD870071420B /* BannerComponent.m in Sources */,
839D916D1EF3E20B0077C7C8 /* RNFirebaseAdMobInterstitial.m in Sources */,

View File

@ -0,0 +1,19 @@
#ifndef RNFirebaseInstanceId_h
#define RNFirebaseInstanceId_h
#import <Foundation/Foundation.h>
#if __has_include(<FirebaseInstanceID/FirebaseInstanceID.h>)
#import <React/RCTBridgeModule.h>
@interface RNFirebaseInstanceId : NSObject <RCTBridgeModule> {
}
@end
#else
@interface RNFirebaseInstanceId : NSObject
@end
#endif
#endif

View File

@ -0,0 +1,35 @@
#import "RNFirebaseInstanceId.h"
#if __has_include(<FirebaseInstanceID/FIRInstanceID.h>)
#import <FirebaseInstanceID/FIRInstanceID.h>
@implementation RNFirebaseInstanceId
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(delete:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[[FIRInstanceID instanceID] deleteIDWithHandler:^(NSError * _Nullable error) {
if (error) {
reject(@"instance_id_error", @"Failed to delete instance id", error);
} else {
resolve(nil);
}
}];
}
RCT_EXPORT_METHOD(get:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[[FIRInstanceID instanceID] getIDWithHandler:^(NSString * _Nullable identity, NSError * _Nullable error) {
if (error) {
reject(@"instance_id_error", @"Failed to get instance id", error);
} else {
resolve(identity);
}
}];
}
@end
#else
@implementation RNFirebaseInstanceId
@end
#endif

View File

@ -1,23 +0,0 @@
#ifndef NewRNFirebaseMessaging_h
#define NewRNFirebaseMessaging_h
#import <Foundation/Foundation.h>
#if __has_include(<FirebaseMessaging/FirebaseMessaging.h>)
#import <FirebaseMessaging/FirebaseMessaging.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface NewRNFirebaseMessaging : RCTEventEmitter<RCTBridgeModule, FIRMessagingDelegate>
#if !TARGET_OS_TV
#endif
@end
#else
@interface NewRNFirebaseMessaging : NSObject
@end
#endif
#endif

View File

@ -1,132 +0,0 @@
#import "NewRNFirebaseMessaging.h"
#if __has_include(<FirebaseMessaging/FirebaseMessaging.h>)
@import UserNotifications;
#import "RNFirebaseEvents.h"
#import "RNFirebaseUtil.h"
#import <FirebaseMessaging/FirebaseMessaging.h>
#import <FirebaseInstanceID/FIRInstanceID.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTConvert.h>
#import <React/RCTUtils.h>
@interface NewRNFirebaseMessaging ()
@end
@implementation NewRNFirebaseMessaging
RCT_EXPORT_MODULE()
- (id)init {
self = [super init];
if (self != nil) {
NSLog(@"Setting up RNFirebaseMessaging instance");
[self initialiseMessaging];
}
return self;
}
- (void)initialiseMessaging {
// Establish Firebase managed data channel
[FIRMessaging messaging].shouldEstablishDirectChannel = YES;
}
- (void)dealloc {
}
// ** Start React Module methods **
RCT_EXPORT_METHOD(getToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([[FIRInstanceID instanceID] token]);
}
RCT_EXPORT_METHOD(requestPermission:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
if (RCTRunningInAppExtension()) {
reject(@"request_permission_unavailable", @"requestPermission is not supported in App Extensions", nil);
return;
}
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
UIUserNotificationType types = (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
[RCTSharedApplication() registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:types categories:nil]];
// Unfortunately on iOS 9 or below, there's no way to tell whether the user accepted or
// rejected the permissions popup
// TODO: Is there something we can listen for?
resolve(@{@"status":@"unknown"});
} else {
// iOS 10 or later
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// For iOS 10 display notification (sent via APNS)
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
resolve(@{@"status": @"granted"});
} else {
reject(@"permission_error", @"Failed to grant permission", error);
}
}];
#endif
}
dispatch_async(dispatch_get_main_queue(), ^{
[RCTSharedApplication() registerForRemoteNotifications];
});
}
// Non Web SDK methods
RCT_EXPORT_METHOD(deleteInstanceId:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[[FIRInstanceID instanceID] deleteIDWithHandler:^(NSError * _Nullable error) {
if (!error) {
resolve(nil);
} else {
reject(@"instance_id_error", @"Failed to delete instance id", error);
}
}];
}
RCT_EXPORT_METHOD(getBadgeNumber: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve(@([RCTSharedApplication() applicationIconBadgeNumber]));
}
RCT_EXPORT_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
UILocalNotification *localUserInfo = [self bridge].launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
if (localUserInfo) {
resolve([[localUserInfo userInfo] copy]);
} else {
resolve([[self bridge].launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy]);
}
}
RCT_EXPORT_METHOD(subscribeToTopic: (NSString*) topic) {
[[FIRMessaging messaging] subscribeToTopic:topic];
}
RCT_EXPORT_METHOD(unsubscribeFromTopic: (NSString*) topic) {
[[FIRMessaging messaging] unsubscribeFromTopic:topic];
}
RCT_EXPORT_METHOD(setBadgeNumber: (NSInteger*) number) {
dispatch_async(dispatch_get_main_queue(), ^{
[RCTSharedApplication() setApplicationIconBadgeNumber:*number];
});
}
- (NSArray<NSString *> *)supportedEvents {
return @[MESSAGING_MESSAGE_RECEIVED, MESSAGING_TOKEN_REFRESHED];
}
+ (BOOL)requiresMainQueueSetup
{
return YES;
}
@end
#else
@implementation NewRNFirebaseMessaging
@end
#endif

View File

@ -7,22 +7,10 @@
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@import UserNotifications;
@interface RNFirebaseMessaging : RCTEventEmitter<RCTBridgeModule, FIRMessagingDelegate>
typedef void (^RCTRemoteNotificationCallback)(UIBackgroundFetchResult result);
typedef void (^RCTWillPresentNotificationCallback)(UNNotificationPresentationOptions result);
typedef void (^RCTNotificationResponseCallback)();
@property (nonatomic, assign) bool connectedToFCM;
#if !TARGET_OS_TV
+ (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo;
+ (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull RCTRemoteNotificationCallback)completionHandler;
+ (void)didReceiveLocalNotification:(nonnull UILocalNotification *)notification;
+ (void)didReceiveNotificationResponse:(nonnull UNNotificationResponse *)response withCompletionHandler:(nonnull RCTNotificationResponseCallback)completionHandler;
+ (void)willPresentNotification:(nonnull UNNotification *)notification withCompletionHandler:(nonnull RCTWillPresentNotificationCallback)completionHandler;
#endif
@end

View File

@ -1,7 +1,7 @@
#import "RNFirebaseMessaging.h"
@import UserNotifications;
#if __has_include(<FirebaseMessaging/FirebaseMessaging.h>)
@import UserNotifications;
#import "RNFirebaseEvents.h"
#import "RNFirebaseUtil.h"
#import <FirebaseMessaging/FirebaseMessaging.h>
@ -11,167 +11,14 @@
#import <React/RCTConvert.h>
#import <React/RCTUtils.h>
@implementation RCTConvert (NSCalendarUnit)
RCT_ENUM_CONVERTER(NSCalendarUnit,
(@{
@"year": @(NSCalendarUnitYear),
@"month": @(NSCalendarUnitMonth),
@"week": @(NSCalendarUnitWeekOfYear),
@"day": @(NSCalendarUnitDay),
@"hour": @(NSCalendarUnitHour),
@"minute": @(NSCalendarUnitMinute)
}),
0,
integerValue)
@end
@implementation RCTConvert (UNNotificationRequest)
+ (UNNotificationRequest *)UNNotificationRequest:(id)json
{
NSDictionary<NSString *, id> *details = [self NSDictionary:json];
UNMutableNotificationContent *content = [UNMutableNotificationContent new];
content.title =[RCTConvert NSString:details[@"title"]];
content.body =[RCTConvert NSString:details[@"body"]];
NSString* sound = [RCTConvert NSString:details[@"sound"]];
if(sound != nil){
content.sound = [UNNotificationSound soundNamed:sound];
}else{
content.sound = [UNNotificationSound defaultSound];
}
content.categoryIdentifier = [RCTConvert NSString:details[@"click_action"]];
content.userInfo = details;
content.badge = [RCTConvert NSNumber:details[@"badge"]];
if([details objectForKey:@"show_in_foreground"] != nil) {
if([(NSNumber *)details[@"show_in_foreground"] boolValue] == YES) {
[content setValue:@YES forKeyPath:@"shouldAlwaysAlertWhileAppIsForeground"];
}
}
NSDate *fireDate = [RCTConvert NSDate:details[@"fire_date"]];
if(fireDate == nil){
return [UNNotificationRequest requestWithIdentifier:[RCTConvert NSString:details[@"id"]] content:content trigger:nil];
}
NSCalendarUnit interval = [RCTConvert NSCalendarUnit:details[@"repeat_interval"]];
NSCalendarUnit unitFlags;
switch (interval) {
case NSCalendarUnitMinute: {
unitFlags = NSCalendarUnitSecond;
break;
}
case NSCalendarUnitHour: {
unitFlags = NSCalendarUnitMinute | NSCalendarUnitSecond;
break;
}
case NSCalendarUnitDay: {
unitFlags = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
break;
}
case NSCalendarUnitWeekOfYear: {
unitFlags = NSCalendarUnitWeekday | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
break;
}
case NSCalendarUnitMonth:{
unitFlags = NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
}
case NSCalendarUnitYear:{
unitFlags = NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
}
default:
unitFlags = NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
break;
}
NSDateComponents *components = [[NSCalendar currentCalendar] components:unitFlags fromDate:fireDate];
UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:interval != 0];
return [UNNotificationRequest requestWithIdentifier:[RCTConvert NSString:details[@"id"]] content:content trigger:trigger];
}
@end
@implementation RCTConvert (UILocalNotification)
+ (UILocalNotification *)UILocalNotification:(id)json
{
NSDictionary<NSString *, id> *details = [self NSDictionary:json];
UILocalNotification *notification = [UILocalNotification new];
notification.fireDate = [RCTConvert NSDate:details[@"fire_date"]] ?: [NSDate date];
if([notification respondsToSelector:@selector(setAlertTitle:)]){
[notification setAlertTitle:[RCTConvert NSString:details[@"title"]]];
}
notification.alertBody = [RCTConvert NSString:details[@"body"]];
notification.alertAction = [RCTConvert NSString:details[@"alert_action"]];
notification.soundName = [RCTConvert NSString:details[@"sound"]] ?: UILocalNotificationDefaultSoundName;
notification.userInfo = details;
notification.category = [RCTConvert NSString:details[@"click_action"]];
notification.repeatInterval = [RCTConvert NSCalendarUnit:details[@"repeat_interval"]];
notification.applicationIconBadgeNumber = [RCTConvert NSInteger:details[@"badge"]];
return notification;
}
RCT_ENUM_CONVERTER(UIBackgroundFetchResult, (@{
@"UIBackgroundFetchResultNewData": @(UIBackgroundFetchResultNewData),
@"UIBackgroundFetchResultNoData": @(UIBackgroundFetchResultNoData),
@"UIBackgroundFetchResultFailed": @(UIBackgroundFetchResultFailed),
}), UIBackgroundFetchResultNoData, integerValue)
RCT_ENUM_CONVERTER(UNNotificationPresentationOptions, (@{
@"UNNotificationPresentationOptionAll": @(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound),
@"UNNotificationPresentationOptionNone": @(UNNotificationPresentationOptionNone)}), UIBackgroundFetchResultNoData, integerValue)
@end
@interface RNFirebaseMessaging ()
@property (nonatomic, strong) NSMutableDictionary *notificationCallbacks;
@end
@implementation RNFirebaseMessaging
RCT_EXPORT_MODULE()
+ (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo {
NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: userInfo];
[data setValue:@"remote_notification" forKey:@"_notificationType"];
[data setValue:@(RCTSharedApplication().applicationState == UIApplicationStateInactive) forKey:@"opened_from_tray"];
[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_NOTIFICATION_RECEIVED object:self userInfo:@{@"data": data}];
}
+ (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull RCTRemoteNotificationCallback)completionHandler {
NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: userInfo];
[data setValue:@"remote_notification" forKey:@"_notificationType"];
[data setValue:@(RCTSharedApplication().applicationState == UIApplicationStateInactive) forKey:@"opened_from_tray"];
[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_NOTIFICATION_RECEIVED object:self userInfo:@{@"data": data, @"completionHandler": completionHandler}];
}
+ (void)didReceiveLocalNotification:(UILocalNotification *)notification {
NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: notification.userInfo];
[data setValue:@"local_notification" forKey:@"_notificationType"];
[data setValue:@(RCTSharedApplication().applicationState == UIApplicationStateInactive) forKey:@"opened_from_tray"];
[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_NOTIFICATION_RECEIVED object:self userInfo:@{@"data": data}];
}
+ (void)willPresentNotification:(UNNotification *)notification withCompletionHandler:(nonnull RCTWillPresentNotificationCallback)completionHandler
{
NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: notification.request.content.userInfo];
[data setValue:@"will_present_notification" forKey:@"_notificationType"];
[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_NOTIFICATION_RECEIVED object:self userInfo:@{@"data": data, @"completionHandler": completionHandler}];
}
+ (void)didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(nonnull RCTNotificationResponseCallback)completionHandler
{
NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: response.notification.request.content.userInfo];
[data setValue:@"notification_response" forKey:@"_notificationType"];
[data setValue:@YES forKey:@"opened_from_tray"];
if (response.actionIdentifier) {
[data setValue:response.actionIdentifier forKey:@"_actionIdentifier"];
}
[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_NOTIFICATION_RECEIVED object:self userInfo:@{@"data": data, @"completionHandler": completionHandler}];
}
- (id)init {
self = [super init];
if (self != nil) {
@ -184,74 +31,56 @@ RCT_EXPORT_MODULE()
- (void)initialiseMessaging {
// Establish Firebase managed data channel
[FIRMessaging messaging].shouldEstablishDirectChannel = YES;
// Set up listeners for data messages
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(sendDataMessageFailure:)
name:FIRMessagingSendErrorNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(sendDataMessageSuccess:)
name:FIRMessagingSendSuccessNotification
object:nil];
// Set up internal listener to send notification over bridge
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleNotificationReceived:)
name:MESSAGING_NOTIFICATION_RECEIVED
object:nil];
// Set this as a delegate for FIRMessaging
dispatch_async(dispatch_get_main_queue(), ^{
[FIRMessaging messaging].delegate = self;
});
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)handleNotificationReceived:(NSNotification *)notification {
id completionHandler = notification.userInfo[@"completionHandler"];
NSMutableDictionary* data = notification.userInfo[@"data"];
if(completionHandler != nil){
NSString *completionHandlerId = [[NSUUID UUID] UUIDString];
if (!self.notificationCallbacks) {
// Lazy initialization
self.notificationCallbacks = [NSMutableDictionary dictionary];
}
self.notificationCallbacks[completionHandlerId] = completionHandler;
data[@"_completionHandlerId"] = completionHandlerId;
}
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_NOTIFICATION_RECEIVED body:data];
}
- (void)sendDataMessageFailure:(NSNotification *)notification {
NSString *messageID = (NSString *)notification.userInfo[@"messageID"];
NSLog(@"sendDataMessageFailure: %@", messageID);
}
- (void)sendDataMessageSuccess:(NSNotification *)notification {
NSString *messageID = (NSString *)notification.userInfo[@"messageID"];
NSLog(@"sendDataMessageSuccess: %@", messageID);
}
// ** Start FIRMessagingDelegate methods **
// Handle data messages in the background
- (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage {
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_NOTIFICATION_RECEIVED body:[remoteMessage appData]];
}
// Listen for token refreshes
- (void)messaging:(nonnull FIRMessaging *)messaging didRefreshRegistrationToken:(nonnull NSString *)fcmToken {
NSLog(@"FCM registration token: %@", fcmToken);
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_TOKEN_REFRESHED body:fcmToken];
}
// ** End FIRMessagingDelegate methods **
// ** Start React Module methods **
RCT_EXPORT_METHOD(getToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([[FIRInstanceID instanceID] token]);
}
RCT_EXPORT_METHOD(requestPermission:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
if (RCTRunningInAppExtension()) {
reject(@"request_permission_unavailable", @"requestPermission is not supported in App Extensions", nil);
return;
}
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
UIUserNotificationType types = (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
[RCTSharedApplication() registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:types categories:nil]];
// Unfortunately on iOS 9 or below, there's no way to tell whether the user accepted or
// rejected the permissions popup
// TODO: Is there something we can listen for?
resolve(@{@"status":@"unknown"});
} else {
// iOS 10 or later
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// For iOS 10 display notification (sent via APNS)
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
resolve(@{@"status": @"granted"});
} else {
reject(@"permission_error", @"Failed to grant permission", error);
}
}];
#endif
}
dispatch_async(dispatch_get_main_queue(), ^{
[RCTSharedApplication() registerForRemoteNotifications];
});
}
// Non Web SDK methods
RCT_EXPORT_METHOD(getBadge: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve(@([RCTSharedApplication() applicationIconBadgeNumber]));
}
RCT_EXPORT_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
UILocalNotification *localUserInfo = [self bridge].launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
if (localUserInfo) {
@ -261,51 +90,9 @@ RCT_EXPORT_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve rejecte
}
}
RCT_EXPORT_METHOD(getToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([FIRMessaging messaging].FCMToken);
}
RCT_EXPORT_METHOD(deleteInstanceId:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
[[FIRInstanceID instanceID] deleteIDWithHandler:^(NSError * _Nullable error) {
if (!error) {
resolve(nil);
} else {
reject(@"instance_id_error", @"Failed to delete instance id", error);
}
}];
}
RCT_EXPORT_METHOD(requestPermissions:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
if (RCTRunningInAppExtension()) {
return;
}
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
UIUserNotificationType allNotificationTypes =
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings =
[UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
[RCTSharedApplication() registerUserNotificationSettings:settings];
// Unfortunately on iOS 9 or below, there's no way to tell whether the user accepted or
// rejected the permissions popup
resolve(@{@"status":@"unknown"});
} else {
// iOS 10 or later
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// For iOS 10 display notification (sent via APNS)
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
UNAuthorizationOptions authOptions =
UNAuthorizationOptionAlert
| UNAuthorizationOptionSound
| UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) {
resolve(@{@"granted":@(granted)});
}];
#endif
}
RCT_EXPORT_METHOD(setBadge: (NSInteger*) number) {
dispatch_async(dispatch_get_main_queue(), ^{
[RCTSharedApplication() registerForRemoteNotifications];
[RCTSharedApplication() setApplicationIconBadgeNumber:*number];
});
}
@ -317,144 +104,8 @@ RCT_EXPORT_METHOD(unsubscribeFromTopic: (NSString*) topic) {
[[FIRMessaging messaging] unsubscribeFromTopic:topic];
}
RCT_EXPORT_METHOD(createLocalNotification:(id)data resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
if([UNUserNotificationCenter currentNotificationCenter] != nil){
UNNotificationRequest* request = [RCTConvert UNNotificationRequest:data];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
resolve(nil);
}else{
reject(@"notification_error", @"Failed to present local notificaton", error);
}
}];
}else{
UILocalNotification* notif = [RCTConvert UILocalNotification:data];
[RCTSharedApplication() presentLocalNotificationNow:notif];
resolve(nil);
}
}
RCT_EXPORT_METHOD(scheduleLocalNotification:(id)data resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
if([UNUserNotificationCenter currentNotificationCenter] != nil){
UNNotificationRequest* request = [RCTConvert UNNotificationRequest:data];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
resolve(nil);
}else{
reject(@"notification_error", @"Failed to present local notificaton", error);
}
}];
}else{
UILocalNotification* notif = [RCTConvert UILocalNotification:data];
[RCTSharedApplication() scheduleLocalNotification:notif];
resolve(nil);
}
}
RCT_EXPORT_METHOD(removeDeliveredNotification:(NSString*) notificationId) {
if([UNUserNotificationCenter currentNotificationCenter] != nil){
[[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers:@[notificationId]];
}
}
RCT_EXPORT_METHOD(removeAllDeliveredNotifications) {
if([UNUserNotificationCenter currentNotificationCenter] != nil){
[[UNUserNotificationCenter currentNotificationCenter] removeAllDeliveredNotifications];
} else {
[RCTSharedApplication() setApplicationIconBadgeNumber: 0];
}
}
RCT_EXPORT_METHOD(cancelAllLocalNotifications) {
if([UNUserNotificationCenter currentNotificationCenter] != nil){
[[UNUserNotificationCenter currentNotificationCenter] removeAllPendingNotificationRequests];
} else {
[RCTSharedApplication() cancelAllLocalNotifications];
}
}
RCT_EXPORT_METHOD(cancelLocalNotification:(NSString*) notificationId) {
if([UNUserNotificationCenter currentNotificationCenter] != nil){
[[UNUserNotificationCenter currentNotificationCenter] removePendingNotificationRequestsWithIdentifiers:@[notificationId]];
} else {
for (UILocalNotification *notification in RCTSharedApplication().scheduledLocalNotifications) {
NSDictionary<NSString *, id> *notificationInfo = notification.userInfo;
if([notificationId isEqualToString:[notificationInfo valueForKey:@"id"]]){
[RCTSharedApplication() cancelLocalNotification:notification];
}
}
}
}
RCT_EXPORT_METHOD(getScheduledLocalNotifications:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
if([UNUserNotificationCenter currentNotificationCenter] != nil){
[[UNUserNotificationCenter currentNotificationCenter] getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> * _Nonnull requests) {
NSMutableArray* list = [[NSMutableArray alloc] init];
for(UNNotificationRequest * notif in requests){
UNMutableNotificationContent *content = notif.content;
[list addObject:content.userInfo];
}
resolve(list);
}];
} else {
NSMutableArray* list = [[NSMutableArray alloc] init];
for(UILocalNotification * notif in [RCTSharedApplication() scheduledLocalNotifications]){
[list addObject:notif.userInfo];
}
resolve(list);
}
}
RCT_EXPORT_METHOD(setBadgeNumber: (NSInteger*) number) {
dispatch_async(dispatch_get_main_queue(), ^{
[RCTSharedApplication() setApplicationIconBadgeNumber:number];
});
}
RCT_EXPORT_METHOD(getBadgeNumber: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve(@([RCTSharedApplication() applicationIconBadgeNumber]));
}
RCT_EXPORT_METHOD(send:(NSDictionary *)remoteMessage) {
int64_t ttl = @([[remoteMessage valueForKey:@"ttl"] intValue]).doubleValue;
NSString * mId = [remoteMessage valueForKey:@"id"];
NSString * receiver = [remoteMessage valueForKey:@"sender"];
NSDictionary * data = [remoteMessage valueForKey:@"data"];
[[FIRMessaging messaging] sendMessage:data to:receiver withMessageID:mId timeToLive:ttl];
}
RCT_EXPORT_METHOD(finishRemoteNotification: (NSString *)completionHandlerId fetchResult:(UIBackgroundFetchResult)result) {
RCTRemoteNotificationCallback completionHandler = self.notificationCallbacks[completionHandlerId];
if (!completionHandler) {
RCTLogError(@"There is no completion handler with completionHandlerId: %@", completionHandlerId);
return;
}
completionHandler(result);
[self.notificationCallbacks removeObjectForKey:completionHandlerId];
}
RCT_EXPORT_METHOD(finishWillPresentNotification: (NSString *)completionHandlerId fetchResult:(UNNotificationPresentationOptions)result) {
RCTWillPresentNotificationCallback completionHandler = self.notificationCallbacks[completionHandlerId];
if (!completionHandler) {
RCTLogError(@"There is no completion handler with completionHandlerId: %@", completionHandlerId);
return;
}
completionHandler(result);
[self.notificationCallbacks removeObjectForKey:completionHandlerId];
}
RCT_EXPORT_METHOD(finishNotificationResponse: (NSString *)completionHandlerId) {
RCTNotificationResponseCallback completionHandler = self.notificationCallbacks[completionHandlerId];
if (!completionHandler) {
RCTLogError(@"There is no completion handler with completionHandlerId: %@", completionHandlerId);
return;
}
completionHandler();
[self.notificationCallbacks removeObjectForKey:completionHandlerId];
}
- (NSArray<NSString *> *)supportedEvents {
return @[MESSAGING_TOKEN_REFRESHED, MESSAGING_NOTIFICATION_RECEIVED];
return @[MESSAGING_MESSAGE_RECEIVED, MESSAGING_TOKEN_REFRESHED];
}
+ (BOOL)requiresMainQueueSetup

View File

@ -0,0 +1,22 @@
#ifndef RNFirebaseNotifications_h
#define RNFirebaseNotifications_h
#import <Foundation/Foundation.h>
#if __has_include(<FirebaseMessaging/FirebaseMessaging.h>)
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface RNFirebaseNotifications : RCTEventEmitter<RCTBridgeModule>
#if !TARGET_OS_TV
#endif
@end
#else
@interface RNFirebaseNotifications : NSObject
@end
#endif
#endif

View File

@ -0,0 +1,14 @@
#import "RNFirebaseNotifications.h"
#if __has_include(<FirebaseMessaging/FIRMessaging.h>)
@implementation RNFirebaseNotifications
RCT_EXPORT_MODULE();
@end
#else
@implementation RNFirebaseNotifications
@end
#endif

View File

@ -18,11 +18,12 @@ import Crashlytics, {
} from '../fabric/crashlytics';
import Database, { NAMESPACE as DatabaseNamespace } from '../database';
import Firestore, { NAMESPACE as FirestoreNamespace } from '../firestore';
import InstanceId, { NAMESPACE as InstanceIdNamespace } from '../instanceid';
import Links, { NAMESPACE as LinksNamespace } from '../links';
import Messaging, { NAMESPACE as MessagingNamespace } from '../messaging';
import NewMessaging, {
NAMESPACE as NewMessagingNamespace,
} from '../messaging/messagingIndex';
import Notifications, {
NAMESPACE as NotificationsNamespace,
} from '../notifications';
import Performance, { NAMESPACE as PerfNamespace } from '../perf';
import Storage, { NAMESPACE as StorageNamespace } from '../storage';
import Utils, { NAMESPACE as UtilsNamespace } from '../utils';
@ -47,9 +48,10 @@ export default class App {
crashlytics: () => Crashlytics,
};
firestore: () => Firestore;
instanceid: () => InstanceId;
links: () => Links;
messaging: () => Messaging;
newmessaging: () => NewMessaging;
notifications: () => Notifications;
perf: () => Performance;
storage: () => Storage;
utils: () => Utils;
@ -87,12 +89,13 @@ export default class App {
crashlytics: APPS.appModule(this, CrashlyticsNamespace, Crashlytics),
};
this.firestore = APPS.appModule(this, FirestoreNamespace, Firestore);
this.instanceid = APPS.appModule(this, InstanceIdNamespace, InstanceId);
this.links = APPS.appModule(this, LinksNamespace, Links);
this.messaging = APPS.appModule(this, MessagingNamespace, Messaging);
this.newmessaging = APPS.appModule(
this.notifications = APPS.appModule(
this,
NewMessagingNamespace,
NewMessaging
NotificationsNamespace,
Notifications
);
this.perf = APPS.appModule(this, PerfNamespace, Performance);
this.storage = APPS.appModule(this, StorageNamespace, Storage);

View File

@ -39,6 +39,10 @@ import {
statics as FirestoreStatics,
MODULE_NAME as FirestoreModuleName,
} from '../firestore';
import {
statics as InstanceIdStatics,
MODULE_NAME as InstanceIdModuleName,
} from '../instanceid';
import {
statics as LinksStatics,
MODULE_NAME as LinksModuleName,
@ -48,9 +52,9 @@ import {
MODULE_NAME as MessagingModuleName,
} from '../messaging';
import {
statics as NewMessagingStatics,
MODULE_NAME as NewMessagingModuleName,
} from '../messaging/messagingIndex';
statics as NotificationsStatics,
MODULE_NAME as NotificationsModuleName,
} from '../notifications';
import {
statics as PerformanceStatics,
MODULE_NAME as PerfModuleName,
@ -74,9 +78,10 @@ import type {
FabricModule,
FirebaseOptions,
FirestoreModule,
InstanceIdModule,
LinksModule,
MessagingModule,
NewMessagingModule,
NotificationsModule,
PerformanceModule,
StorageModule,
UtilsModule,
@ -93,9 +98,10 @@ class Firebase {
database: DatabaseModule;
fabric: FabricModule;
firestore: FirestoreModule;
instanceid: InstanceIdModule;
links: LinksModule;
messaging: MessagingModule;
newmessaging: NewMessagingModule;
notifications: NotificationsModule;
perf: PerformanceModule;
storage: StorageModule;
utils: UtilsModule;
@ -137,16 +143,21 @@ class Firebase {
FirestoreStatics,
FirestoreModuleName
);
this.instanceid = APPS.moduleAndStatics(
'instanceid',
InstanceIdStatics,
InstanceIdModuleName
);
this.links = APPS.moduleAndStatics('links', LinksStatics, LinksModuleName);
this.messaging = APPS.moduleAndStatics(
'messaging',
MessagingStatics,
MessagingModuleName
);
this.newmessaging = APPS.moduleAndStatics(
'newmessaging',
NewMessagingStatics,
NewMessagingModuleName
this.notifications = APPS.moduleAndStatics(
'notifications',
NotificationsStatics,
NotificationsModuleName
);
this.perf = APPS.moduleAndStatics(
'perf',

View File

@ -0,0 +1,31 @@
/**
* @flow
* Instance ID representation wrapper
*/
import ModuleBase from '../../utils/ModuleBase';
import { getNativeModule } from '../../utils/native';
import type App from '../core/firebase-app';
export const MODULE_NAME = 'RNFirebaseInstanceId';
export const NAMESPACE = 'instanceid';
export default class InstanceId extends ModuleBase {
constructor(app: App) {
super(app, {
moduleName: MODULE_NAME,
multiApp: false,
namespace: NAMESPACE,
});
}
delete(): Promise<void> {
return getNativeModule(this).delete();
}
get(): Promise<string> {
return getNativeModule(this).get();
}
}
export const statics = {};

View File

@ -1,94 +1,69 @@
/**
* @flow
* Messaging representation wrapper
* Messaging (FCM) representation wrapper
*/
import { Platform, NativeModules } from 'react-native';
import { SharedEventEmitter } from '../../utils/events';
import INTERNALS from '../../utils/internals';
import { getLogger } from '../../utils/log';
import ModuleBase from '../../utils/ModuleBase';
import RemoteMessage from './RemoteMessage';
import { getNativeModule } from '../../utils/native';
import { isFunction, isObject } from '../../utils';
import type App from '../core/firebase-app';
const EVENT_TYPE = {
RefreshToken: 'messaging_token_refreshed',
Notification: 'messaging_notification_received',
type Notification = {
body: string,
bodyLocalizationArgs: string[],
bodyLocalizationKey: string,
clickAction: string,
color: string,
icon: string,
link: string,
sound: string,
tag: string,
title: string,
titleLocalizationArgs: string[],
titleLocalizationKey: string,
};
const NOTIFICATION_TYPE = {
Remote: 'remote_notification',
NotificationResponse: 'notification_response',
WillPresent: 'will_present_notification',
Local: 'local_notification',
type Message = {
collapseKey: string,
data: { [string]: string },
from: string,
messageId: string,
messageType?: string,
openedFromTray: boolean,
notification?: Notification,
sentTime: number,
to?: string,
ttl?: number,
};
const REMOTE_NOTIFICATION_RESULT = {
NewData: 'UIBackgroundFetchResultNewData',
NoData: 'UIBackgroundFetchResultNoData',
ResultFailed: 'UIBackgroundFetchResultFailed',
type OnMessage = Message => any;
type OnMessageObserver = {
next: OnMessage,
};
const WILL_PRESENT_RESULT = {
All: 'UNNotificationPresentationOptionAll',
None: 'UNNotificationPresentationOptionNone',
type OnTokenRefresh = String => any;
type OnTokenRefreshObserver = {
next: OnTokenRefresh,
};
const NATIVE_EVENTS = [EVENT_TYPE.RefreshToken, EVENT_TYPE.Notification];
type RemoteMessage = {
collapseKey?: string,
data: { [string]: string },
messageId?: string,
messageType?: string,
to: string,
ttl: number,
};
const FirebaseMessaging = NativeModules.RNFirebaseMessaging;
/**
* IOS only finish function
* @param data
*/
function finish(data) {
if (Platform.OS !== 'ios') {
return;
}
if (!this._finishCalled && this._completionHandlerId) {
let result = data;
this._finishCalled = true;
switch (this._notificationType) {
case NOTIFICATION_TYPE.Remote:
result = result || REMOTE_NOTIFICATION_RESULT.NoData;
if (!Object.values(REMOTE_NOTIFICATION_RESULT).includes(result)) {
throw new Error(
'Invalid REMOTE_NOTIFICATION_RESULT value, use messaging().REMOTE_NOTIFICATION_RESULT'
);
}
FirebaseMessaging.finishRemoteNotification(
this._completionHandlerId,
result
);
return;
case NOTIFICATION_TYPE.NotificationResponse:
FirebaseMessaging.finishNotificationResponse(this._completionHandlerId);
return;
case NOTIFICATION_TYPE.WillPresent:
result =
result ||
(this.show_in_foreground
? WILL_PRESENT_RESULT.All
: WILL_PRESENT_RESULT.None);
if (!Object.values(WILL_PRESENT_RESULT).includes(result)) {
throw new Error(
'Invalid WILL_PRESENT_RESULT value, use messaging().WILL_PRESENT_RESULT'
);
}
FirebaseMessaging.finishWillPresentNotification(
this._completionHandlerId,
result
);
break;
default:
}
}
}
const NATIVE_EVENTS = [
'messaging_message_received',
'messaging_token_refreshed',
];
export const MODULE_NAME = 'RNFirebaseMessaging';
export const NAMESPACE = 'messaging';
@ -104,204 +79,139 @@ export default class Messaging extends ModuleBase {
multiApp: false,
namespace: NAMESPACE,
});
SharedEventEmitter.addListener(
// sub to internal native event - this fans out to
// public event name: onMessage
'messaging_message_received',
(message: Message) => {
SharedEventEmitter.emit('onMessage', message);
}
);
SharedEventEmitter.addListener(
// sub to internal native event - this fans out to
// public event name: onMessage
'messaging_token_refreshed',
(token: string) => {
SharedEventEmitter.emit('onTokenRefresh', token);
}
);
}
get EVENT_TYPE(): Object {
return EVENT_TYPE;
}
get NOTIFICATION_TYPE(): Object {
return NOTIFICATION_TYPE;
}
get REMOTE_NOTIFICATION_RESULT(): Object {
return REMOTE_NOTIFICATION_RESULT;
}
get WILL_PRESENT_RESULT(): Object {
return WILL_PRESENT_RESULT;
}
/**
* Returns the notification that triggered application open
* @returns {*}
*/
getInitialNotification(): Promise<Object> {
return getNativeModule(this).getInitialNotification();
}
/**
* Returns the fcm token for the current device
* @returns {*|Promise.<String>}
*/
getToken(): Promise<string> {
return getNativeModule(this).getToken();
}
/**
* Reset Instance ID and revokes all tokens.
* @returns {*|Promise.<*>}
*/
deleteInstanceId(): Promise<void> {
return getNativeModule(this).deleteInstanceId();
}
/**
* Create and display a local notification
* @param notification
* @returns {*}
*/
createLocalNotification(notification: Object): Promise<void> {
const _notification = Object.assign({}, notification);
_notification.id = _notification.id || new Date().getTime().toString();
_notification.local_notification = true;
return getNativeModule(this).createLocalNotification(_notification);
}
/**
*
* @param notification
* @returns {*}
*/
scheduleLocalNotification(notification: Object): Promise<void> {
const _notification = Object.assign({}, notification);
if (!notification.id)
return Promise.reject(
new Error('An id is required to schedule a local notification.')
onMessage(nextOrObserver: OnMessage | OnMessageObserver): () => any {
let listener;
if (isFunction(nextOrObserver)) {
listener = nextOrObserver;
} else if (isObject(nextOrObserver) && isFunction(nextOrObserver.next)) {
listener = nextOrObserver.next;
} else {
throw new Error(
'Messaging.onMessage failed: First argument must be a function or observer object with a `next` function.'
);
_notification.local_notification = true;
return getNativeModule(this).scheduleLocalNotification(_notification);
}
// TODO: iOS finish
getLogger(this).info('Creating onMessage listener');
SharedEventEmitter.addListener('onMessage', listener);
return () => {
getLogger(this).info('Removing onMessage listener');
SharedEventEmitter.removeListener('onMessage', listener);
};
}
onTokenRefresh(
nextOrObserver: OnTokenRefresh | OnTokenRefreshObserver
): () => any {
let listener;
if (isFunction(nextOrObserver)) {
listener = nextOrObserver;
} else if (isObject(nextOrObserver) && isFunction(nextOrObserver.next)) {
listener = nextOrObserver.next;
} else {
throw new Error(
'Messaging.OnTokenRefresh failed: First argument must be a function or observer object with a `next` function.'
);
}
getLogger(this).info('Creating onTokenRefresh listener');
SharedEventEmitter.addListener('onTokenRefresh', listener);
return () => {
getLogger(this).info('Removing onTokenRefresh listener');
SharedEventEmitter.removeListener('onTokenRefresh', listener);
};
}
// TODO: Permission structure?
requestPermission(): Promise<void> {
return getNativeModule(this).requestPermission();
}
/**
* Returns an array of all scheduled notifications
* @returns {Promise.<Array>}
* NON WEB-SDK METHODS
*/
getScheduledLocalNotifications(): Promise<Object[]> {
return getNativeModule(this).getScheduledLocalNotifications();
getBadge(): Promise<number> {
return getNativeModule(this).getBadge();
}
/**
* Cancel a local notification by id - using '*' will cancel
* all local notifications.
* @param id
* @returns {*}
*/
cancelLocalNotification(id: string): Promise<void> {
if (!id) return Promise.reject(new Error('Missing notification id'));
if (id === '*') return getNativeModule(this).cancelAllLocalNotifications();
return getNativeModule(this).cancelLocalNotification(id);
getInitialMessage(): Promise<?Message> {
return getNativeModule(this).getInitialMessage();
}
/**
* Remove a delivered notification - using '*' will remove
* all delivered notifications.
* @param id
* @returns {*}
*/
removeDeliveredNotification(id: string): Promise<void> {
if (!id) return Promise.reject(new Error('Missing notification id'));
if (id === '*')
return getNativeModule(this).removeAllDeliveredNotifications();
return getNativeModule(this).removeDeliveredNotification(id);
sendMessage(remoteMessage: RemoteMessage): Promise<void> {
return getNativeModule(this).send(remoteMessage);
}
/**
* Request notification permission
* @platforms ios
* @returns {*|Promise.<*>}
*/
requestPermissions(): Promise<void> {
return getNativeModule(this).requestPermissions();
setBadge(badge: number): void {
getNativeModule(this).setBadge(badge);
}
/**
* Set notification count badge number
* @param n
*/
setBadgeNumber(n: number): void {
getNativeModule(this).setBadgeNumber(n);
}
/**
* set notification count badge number
* @returns {Promise.<Number>}
*/
getBadgeNumber(): Promise<number> {
return getNativeModule(this).getBadgeNumber();
}
/**
* Subscribe to messages / notifications
* @param listener
* @returns {*}
*/
onMessage(listener: Object => any): () => any {
const rnListener = SharedEventEmitter.addListener(
EVENT_TYPE.Notification,
async event => {
const data = {
...event,
finish,
};
await listener(data);
if (!data._finishCalled) {
data.finish();
}
}
);
return () => rnListener.remove();
}
/**
* Subscribe to token refresh events
* @param listener
* @returns {*}
*/
onTokenRefresh(listener: string => any): () => any {
const rnListener = SharedEventEmitter.addListener(
EVENT_TYPE.RefreshToken,
listener
);
return () => rnListener.remove();
}
/**
* Subscribe to a topic
* @param topic
*/
subscribeToTopic(topic: string): void {
getNativeModule(this).subscribeToTopic(topic);
}
/**
* Unsubscribe from a topic
* @param topic
*/
unsubscribeFromTopic(topic: string): void {
getNativeModule(this).unsubscribeFromTopic(topic);
}
/**
* Send an upstream message
* @param remoteMessage
* KNOWN UNSUPPORTED METHODS
*/
send(remoteMessage: RemoteMessage): Promise<void> {
if (!(remoteMessage instanceof RemoteMessage)) {
throw new Error(
'messaging().send requires an instance of RemoteMessage as the first argument.'
);
}
return getNativeModule(this).send(remoteMessage.toJSON());
deleteToken() {
throw new Error(
INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(
'messaging',
'deleteToken'
)
);
}
setBackgroundMessageHandler() {
throw new Error(
INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(
'messaging',
'setBackgroundMessageHandler'
)
);
}
useServiceWorker() {
throw new Error(
INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(
'messaging',
'useServiceWorker'
)
);
}
}
export const statics = {
EVENT_TYPE,
NOTIFICATION_TYPE,
REMOTE_NOTIFICATION_RESULT,
WILL_PRESENT_RESULT,
RemoteMessage,
// RemoteMessage,
};

View File

@ -1,186 +0,0 @@
/**
* @flow
* Messaging (FCM) representation wrapper
*/
import { SharedEventEmitter } from '../../utils/events';
import INTERNALS from '../../utils/internals';
import { getLogger } from '../../utils/log';
import ModuleBase from '../../utils/ModuleBase';
import { getNativeModule } from '../../utils/native';
import { isFunction, isObject } from '../../utils';
import type App from '../core/firebase-app';
type Message = {
// TODO
};
type OnMessage = Message => any;
type OnMessageObserver = {
next: OnMessage,
};
type OnTokenRefresh = String => any;
type OnTokenRefreshObserver = {
next: OnTokenRefresh,
};
type RemoteMessage = {
// TODO
};
const NATIVE_EVENTS = [
'messaging_message_received',
'messaging_token_refreshed',
];
export const MODULE_NAME = 'NewRNFirebaseMessaging';
export const NAMESPACE = 'newmessaging';
/**
* @class Messaging
*/
export default class Messaging extends ModuleBase {
constructor(app: App) {
super(app, {
events: NATIVE_EVENTS,
moduleName: MODULE_NAME,
multiApp: false,
namespace: NAMESPACE,
});
SharedEventEmitter.addListener(
// sub to internal native event - this fans out to
// public event name: onMessage
'messaging_message_received',
(message: Message) => {
SharedEventEmitter.emit('onMessage', message);
}
);
SharedEventEmitter.addListener(
// sub to internal native event - this fans out to
// public event name: onMessage
'messaging_token_refreshed',
(token: string) => {
SharedEventEmitter.emit('onTokenRefresh', token);
}
);
}
deleteToken(token: string): Promise<void> {
return getNativeModule(this).deleteToken(token);
}
getToken(): Promise<string> {
return getNativeModule(this).getToken();
}
onMessage(nextOrObserver: OnMessage | OnMessageObserver): () => any {
let listener;
if (isFunction(nextOrObserver)) {
listener = nextOrObserver;
} else if (isObject(nextOrObserver) && isFunction(nextOrObserver.next)) {
listener = nextOrObserver.next;
} else {
throw new Error(
'Messaging.onMessage failed: First argument must be a function or observer object with a `next` function.'
);
}
// TODO: iOS finish
getLogger(this).info('Creating onMessage listener');
SharedEventEmitter.addListener('onMessage', listener);
return () => {
getLogger(this).info('Removing onMessage listener');
SharedEventEmitter.removeListener('onMessage', listener);
};
}
onTokenRefresh(
nextOrObserver: OnTokenRefresh | OnTokenRefreshObserver
): () => any {
let listener;
if (isFunction(nextOrObserver)) {
listener = nextOrObserver;
} else if (isObject(nextOrObserver) && isFunction(nextOrObserver.next)) {
listener = nextOrObserver.next;
} else {
throw new Error(
'Messaging.OnTokenRefresh failed: First argument must be a function or observer object with a `next` function.'
);
}
getLogger(this).info('Creating onTokenRefresh listener');
SharedEventEmitter.addListener('onTokenRefresh', listener);
return () => {
getLogger(this).info('Removing onTokenRefresh listener');
SharedEventEmitter.removeListener('onTokenRefresh', listener);
};
}
requestPermission(): Promise<void> {
return getNativeModule(this).requestPermission();
}
/**
* NON WEB-SDK METHODS
*/
deleteInstanceId(): Promise<void> {
return getNativeModule(this).deleteInstanceId();
}
getBadgeNumber(): Promise<number> {
return getNativeModule(this).getBadgeNumber();
}
getInitialMessage(): Promise<Message> {
return getNativeModule(this).getInitialMessage();
}
sendMessage(remoteMessage: RemoteMessage): Promise<void> {
return getNativeModule(this).send(remoteMessage);
}
setBadgeNumber(badge: number): void {
getNativeModule(this).setBadgeNumber(badge);
}
subscribeToTopic(topic: string): void {
getNativeModule(this).subscribeToTopic(topic);
}
unsubscribeFromTopic(topic: string): void {
getNativeModule(this).unsubscribeFromTopic(topic);
}
/**
* KNOWN UNSUPPORTED METHODS
*/
setBackgroundMessageHandler() {
throw new Error(
INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(
'messaging',
'setBackgroundMessageHandler'
)
);
}
useServiceWorker() {
throw new Error(
INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(
'messaging',
'useServiceWorker'
)
);
}
}
export const statics = {
// RemoteMessage,
};

View File

@ -108,19 +108,24 @@ export default class Notifications extends ModuleBase {
}
/**
* Remove a delivered notification - using '*' will remove
* all delivered notifications.
* Remove a delivered notification.
* @param id
* @returns {*}
*/
removeDeliveredNotification(id: string): Promise<void> {
if (!id) return Promise.reject(new Error('Missing notification id'));
if (id === '*') {
return getNativeModule(this).removeAllDeliveredNotifications();
}
return getNativeModule(this).removeDeliveredNotification(id);
}
/**
* Remove all delivered notifications.
* @param id
* @returns {*}
*/
removeDeliveredNotifications(): Promise<void> {
return getNativeModule(this).removeDeliveredNotifications();
}
/**
*
* @param notification
@ -136,3 +141,5 @@ export default class Notifications extends ModuleBase {
return getNativeModule(this).scheduleLocalNotification(_notification);
}
}
export const statics = {};

View File

@ -15,12 +15,14 @@ import type Database from '../modules/database';
import { typeof statics as DatabaseStatics } from '../modules/database';
import type Firestore from '../modules/firestore';
import { typeof statics as FirestoreStatics } from '../modules/firestore';
import type InstanceId from '../modules/instanceid';
import { typeof statics as InstanceIdStatics } from '../modules/instanceid';
import type Links from '../modules/links';
import { typeof statics as LinksStatics } from '../modules/links';
import type Messaging from '../modules/messaging';
import { typeof statics as MessagingStatics } from '../modules/messaging';
import type NewMessaging from '../modules/messaging/messagingIndex';
import { typeof statics as NewMessagingStatics } from '../modules/messaging/messagingIndex';
import type Notifications from '../modules/notifications';
import { typeof statics as NotificationsStatics } from '../modules/notifications';
import type ModuleBase from '../utils/ModuleBase';
import type Performance from '../modules/perf';
import { typeof statics as PerformanceStatics } from '../modules/perf';
@ -58,9 +60,9 @@ export type FirebaseModuleName =
| 'RNFirebaseCrashlytics'
| 'RNFirebaseDatabase'
| 'RNFirebaseFirestore'
| 'RNFirebaseInstanceId'
| 'RNFirebaseLinks'
| 'RNFirebaseMessaging'
| 'NewRNFirebaseMessaging'
| 'RNFirebaseNotifications'
| 'RNFirebasePerformance'
| 'RNFirebaseStorage'
@ -75,9 +77,9 @@ export type FirebaseNamespace =
| 'crashlytics'
| 'database'
| 'firestore'
| 'instanceid'
| 'links'
| 'messaging'
| 'newmessaging'
| 'notifications'
| 'perf'
| 'storage'
@ -209,6 +211,13 @@ export type FirestoreWriteOptions = {
merge?: boolean,
};
/* InstanceId types */
export type InstanceIdModule = {
(): InstanceId,
nativeModuleExists: boolean,
} & InstanceIdStatics;
/* Links types */
export type LinksModule = {
@ -223,10 +232,12 @@ export type MessagingModule = {
nativeModuleExists: boolean,
} & MessagingStatics;
export type NewMessagingModule = {
(): NewMessaging,
/* Notifications types */
export type NotificationsModule = {
(): Notifications,
nativeModuleExists: boolean,
} & NewMessagingStatics;
} & NotificationsStatics;
/* Performance types */

View File

@ -13,10 +13,10 @@
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:launchMode="singleTop"
android:launchMode="singleTask"
android:theme="@style/AppTheme">
<service
android:name="io.invertase.firebase.messaging.MessagingService"
android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
@ -24,7 +24,7 @@
</intent-filter>
</service>
<service android:name="io.invertase.firebase.messaging.InstanceIdService" android:exported="false">
<service android:name="io.invertase.firebase.messaging.RNFirebaseInstanceIdService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
@ -34,6 +34,7 @@
android:name=".MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -42,5 +43,4 @@
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>

View File

@ -12,6 +12,7 @@ import io.invertase.firebase.crash.RNFirebaseCrashPackage;
import io.invertase.firebase.database.RNFirebaseDatabasePackage;
import io.invertase.firebase.fabric.crashlytics.RNFirebaseCrashlyticsPackage;
import io.invertase.firebase.firestore.RNFirebaseFirestorePackage;
import io.invertase.firebase.instanceid.RNFirebaseInstanceIdPackage;
import io.invertase.firebase.links.RNFirebaseLinksPackage;
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage;
import io.invertase.firebase.perf.RNFirebasePerformancePackage;
@ -47,6 +48,7 @@ public class MainApplication extends Application implements ReactApplication {
new RNFirebaseCrashlyticsPackage(),
new RNFirebaseDatabasePackage(),
new RNFirebaseFirestorePackage(),
new RNFirebaseInstanceIdPackage(),
new RNFirebaseLinksPackage(),
new RNFirebaseMessagingPackage(),
new RNFirebasePerformancePackage(),

View File

@ -7,19 +7,30 @@ import DatabaseContents from './tests/support/DatabaseContents';
RNfirebase.database.enableLogging(true);
RNfirebase.firestore.enableLogging(true);
RNfirebase.newmessaging()
.requestPermission()
.then(response => {
console.log('requestPermission:', response);
RNfirebase.newmessaging()
.getToken()
.then(token => {
console.log('token: ', token);
});
})
.catch(error => {
console.error('requestPermission:', error);
});
RNfirebase.messaging().onMessage(message => {
console.log('got new message: ', message);
});
RNfirebase.messaging().onTokenRefresh(token => {
console.log('got new token: ', token);
});
const init = async () => {
try {
await RNfirebase.messaging().requestPermission();
const instanceid = await RNfirebase.instanceid().get();
console.log('instanceid: ', instanceid);
const token = await RNfirebase.messaging().getToken();
console.log('token: ', token);
const initialMessage = await RNfirebase.messaging().getInitialMessage();
console.log('initial message: ', initialMessage);
// RNfirebase.instanceid().delete();
} catch (error) {
console.error('messaging init error:', error);
}
};
init();
const config = {
apiKey: 'AIzaSyDnVqNhxU0Biit9nCo4RorAh5ulQQwko3E',