Skip to content

Commit

Permalink
[messaging] Support FCM data-only messages in the background
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbianca committed Mar 8, 2018
1 parent 57ffa9b commit 7ce7f5a
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
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;
Expand All @@ -21,8 +20,6 @@

import io.invertase.firebase.Utils;

import java.util.Map;

public class RNFirebaseMessaging extends ReactContextBaseJavaModule {
private static final String TAG = "RNFirebaseMessaging";

Expand Down Expand Up @@ -115,44 +112,11 @@ public void onReceive(Context context, Intent intent) {
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
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";
Expand All @@ -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);
// 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, pass to the messaging module
event = new Intent(MESSAGE_EVENT);
event.putExtra("message", message);
// 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(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());
}
}

// Broadcast it so it is only available to the RN Application
LocalBroadcastManager.getInstance(this).sendBroadcast(event);
}
}
2 changes: 2 additions & 0 deletions tests/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
6 changes: 6 additions & 0 deletions tests/index.js
Original file line number Diff line number Diff line change
@@ -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 changes: 17 additions & 0 deletions tests/src/bgMessaging.js
Original file line number Diff line number Diff line change
@@ -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();
};

0 comments on commit 7ce7f5a

Please sign in to comment.