[messaging] Support FCM data-only messages in the background

This commit is contained in:
Chris Bianca 2018-03-08 09:28:27 +00:00
parent 57ffa9bd3e
commit 7ce7f5ae58
7 changed files with 123 additions and 49 deletions

View File

@ -0,0 +1,43 @@
package io.invertase.firebase.messaging;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.google.firebase.messaging.RemoteMessage;
import java.util.Map;
public class MessagingSerializer {
public static WritableMap parseRemoteMessage(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());
}
messageMap.putDouble("sentTime", message.getSentTime());
if (message.getTo() != null) {
messageMap.putString("to", message.getTo());
}
messageMap.putDouble("ttl", message.getTtl());
return messageMap;
}
}

View File

@ -0,0 +1,30 @@
package io.invertase.firebase.messaging;
import android.content.Intent;
import android.os.Bundle;
import com.facebook.react.HeadlessJsTaskService;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
import com.google.firebase.messaging.RemoteMessage;
import javax.annotation.Nullable;
public class RNFirebaseBackgroundMessagingService extends HeadlessJsTaskService {
@Override
protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
RemoteMessage message = intent.getParcelableExtra("message");
WritableMap messageMap = MessagingSerializer.parseRemoteMessage(message);
return new HeadlessJsTaskConfig(
"RNFirebaseBackgroundMessage",
messageMap,
10000,
false
);
}
return null;
}
}

View File

@ -7,7 +7,6 @@ import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
@ -21,8 +20,6 @@ import com.google.firebase.messaging.RemoteMessage;
import io.invertase.firebase.Utils;
import java.util.Map;
public class RNFirebaseMessaging extends ReactContextBaseJavaModule {
private static final String TAG = "RNFirebaseMessaging";
@ -115,44 +112,11 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule {
Log.d(TAG, "Received new message");
RemoteMessage message = intent.getParcelableExtra("message");
WritableMap messageMap = buildMessageMap(message);
WritableMap messageMap = MessagingSerializer.parseRemoteMessage(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());
}
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 {

View File

@ -4,9 +4,12 @@ import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.facebook.react.HeadlessJsTaskService;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import io.invertase.firebase.Utils;
public class RNFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "RNFMessagingService";
public static final String MESSAGE_EVENT = "messaging-message";
@ -16,19 +19,28 @@ public class RNFirebaseMessagingService extends FirebaseMessagingService {
public void onMessageReceived(RemoteMessage message) {
Log.d(TAG, "onMessageReceived event received");
Intent event;
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);
}
// It's a notification, pass to the Notifications module
Intent notificationEvent = new Intent(REMOTE_NOTIFICATION_EVENT);
notificationEvent.putExtra("notification", message);
// Broadcast it to the (foreground) RN Application
LocalBroadcastManager.getInstance(this).sendBroadcast(notificationEvent);
} else {
// It's a data message
// If the app is in the foreground we send it to the Messaging module
if (Utils.isAppInForeground(this.getApplicationContext())) {
Intent messagingEvent = new Intent(MESSAGE_EVENT);
messagingEvent.putExtra("message", message);
// Broadcast it so it is only available to the RN Application
LocalBroadcastManager.getInstance(this).sendBroadcast(event);
LocalBroadcastManager.getInstance(this).sendBroadcast(messagingEvent);
} else {
// If the app is in the background we send it to the Headless JS Service
Intent headlessIntent = new Intent(this.getApplicationContext(), RNFirebaseBackgroundMessagingService.class);
headlessIntent.putExtra("message", message);
this.getApplicationContext().startService(headlessIntent);
HeadlessJsTaskService.acquireWakeLockNow(this.getApplicationContext());
}
}
}
}

View File

@ -30,6 +30,8 @@
</intent-filter>
</service>
<service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" />
<receiver android:name="io.invertase.firebase.notifications.RNFirebaseNotificationReceiver"/>
<receiver android:enabled="true" android:exported="true" android:name="io.invertase.firebase.notifications.RNFirebaseNotificationsRebootReceiver">
<intent-filter>

View File

@ -1,4 +1,10 @@
import { AppRegistry } from 'react-native';
import bootstrap from './src/main';
import bgMessaging from './src/bgMessaging';
AppRegistry.registerComponent('ReactNativeFirebaseDemo', () => bootstrap);
// Task registered to handle background data-only FCM messages
AppRegistry.registerHeadlessTask(
'RNFirebaseBackgroundMessage',
() => bgMessaging
);

17
tests/src/bgMessaging.js Normal file
View File

@ -0,0 +1,17 @@
import RNfirebase from './../firebase';
export default async message => {
console.log('Message', message);
const notification = new RNfirebase.notifications.Notification();
notification
.setTitle('Background notification')
.setBody('Background body')
.setNotificationId('background')
.android.setChannelId('test')
.android.setClickAction('action')
.android.setPriority(RNfirebase.notifications.Android.Priority.Max);
await RNfirebase.notifications().displayNotification(notification);
return Promise.resolve();
};