[js][ios][android][messaging] full implementation of upstream send including RemoteMessage builder
This commit is contained in:
parent
48e57d2065
commit
91e9263965
@ -156,35 +156,30 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements L
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void send(String senderId, ReadableMap payload) throws Exception {
|
public void send(ReadableMap remoteMessage) {
|
||||||
FirebaseMessaging fm = FirebaseMessaging.getInstance();
|
FirebaseMessaging fm = FirebaseMessaging.getInstance();
|
||||||
RemoteMessage.Builder message = new RemoteMessage.Builder(senderId + "@gcm.googleapis.com")
|
RemoteMessage.Builder message = new RemoteMessage.Builder(remoteMessage.getString("sender"));
|
||||||
.setMessageId(UUID.randomUUID().toString());
|
|
||||||
|
|
||||||
ReadableMapKeySetIterator iterator = payload.keySetIterator();
|
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()) {
|
while (iterator.hasNextKey()) {
|
||||||
String key = iterator.nextKey();
|
String key = iterator.nextKey();
|
||||||
String value = getStringFromReadableMap(payload, key);
|
String value = data.getString(key);
|
||||||
message.addData(key, value);
|
message.addData(key, value);
|
||||||
}
|
}
|
||||||
fm.send(message.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getStringFromReadableMap(ReadableMap map, String key) throws Exception {
|
fm.send(message.build());
|
||||||
switch (map.getType(key)) {
|
|
||||||
case String:
|
|
||||||
return map.getString(key);
|
|
||||||
case Number:
|
|
||||||
try {
|
|
||||||
return String.valueOf(map.getInt(key));
|
|
||||||
} catch (Exception e) {
|
|
||||||
return String.valueOf(map.getDouble(key));
|
|
||||||
}
|
|
||||||
case Boolean:
|
|
||||||
return String.valueOf(map.getBoolean(key));
|
|
||||||
default:
|
|
||||||
throw new Exception("Unknown data type: " + map.getType(key).name() + " for message key " + key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerMessageHandler() {
|
private void registerMessageHandler() {
|
||||||
|
@ -278,7 +278,7 @@ RCT_EXPORT_METHOD(requestPermissions:(RCTPromiseResolveBlock)resolve rejecter:(R
|
|||||||
[[UNUserNotificationCenter currentNotificationCenter]
|
[[UNUserNotificationCenter currentNotificationCenter]
|
||||||
requestAuthorizationWithOptions:authOptions
|
requestAuthorizationWithOptions:authOptions
|
||||||
completionHandler:^(BOOL granted, NSError * _Nullable error) {
|
completionHandler:^(BOOL granted, NSError * _Nullable error) {
|
||||||
resolve(@{@"granted":@(granted)});
|
resolve(@{@"granted":@(granted)});
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
#endif
|
#endif
|
||||||
@ -408,23 +408,12 @@ RCT_EXPORT_METHOD(getBadgeNumber: (RCTPromiseResolveBlock)resolve rejecter:(RCTP
|
|||||||
resolve(@([RCTSharedApplication() applicationIconBadgeNumber]));
|
resolve(@([RCTSharedApplication() applicationIconBadgeNumber]));
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(send:(NSString*)senderId withPayload:(NSDictionary *)message)
|
RCT_EXPORT_METHOD(send:(NSDictionary *)remoteMessage) {
|
||||||
{
|
int64_t ttl = @([[remoteMessage valueForKey:@"ttl"] intValue]).doubleValue;
|
||||||
NSMutableDictionary * mMessage = [message mutableCopy];
|
NSString * mId = [[remoteMessage valueForKey:@"id"] stringValue];
|
||||||
NSMutableDictionary * upstreamMessage = [[NSMutableDictionary alloc] init];
|
NSString * receiver = [[remoteMessage valueForKey:@"senderId"] stringValue];
|
||||||
for (NSString* key in mMessage) {
|
NSDictionary * data = [[remoteMessage valueForKey:@"data"] dictionaryRepresentation];
|
||||||
upstreamMessage[key] = [NSString stringWithFormat:@"%@", [mMessage valueForKey:key]];
|
[[FIRMessaging messaging]sendMessage:data to:receiver withMessageID:mId timeToLive:ttl];
|
||||||
}
|
|
||||||
|
|
||||||
NSDictionary *imMessage = [NSDictionary dictionaryWithDictionary:upstreamMessage];
|
|
||||||
|
|
||||||
int64_t ttl = 3600;
|
|
||||||
NSString * receiver = [NSString stringWithFormat:@"%@@gcm.googleapis.com", senderId];
|
|
||||||
|
|
||||||
NSUUID *uuid = [NSUUID UUID];
|
|
||||||
NSString * messageID = [uuid UUIDString];
|
|
||||||
|
|
||||||
[[FIRMessaging messaging]sendMessage:imMessage to:receiver withMessageID:messageID timeToLive:ttl];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(finishRemoteNotification: (NSString *)completionHandlerId fetchResult:(UIBackgroundFetchResult)result){
|
RCT_EXPORT_METHOD(finishRemoteNotification: (NSString *)completionHandlerId fetchResult:(UIBackgroundFetchResult)result){
|
||||||
|
@ -11,7 +11,7 @@ import { isObject } from './utils';
|
|||||||
import Auth, { statics as AuthStatics } from './modules/auth';
|
import Auth, { statics as AuthStatics } from './modules/auth';
|
||||||
import Storage, { statics as StorageStatics } from './modules/storage';
|
import Storage, { statics as StorageStatics } from './modules/storage';
|
||||||
import Database, { statics as DatabaseStatics } from './modules/database';
|
import Database, { statics as DatabaseStatics } from './modules/database';
|
||||||
import Messaging from './modules/messaging';
|
import Messaging, { statics as MessagingStatics } from './modules/messaging';
|
||||||
import Analytics from './modules/analytics';
|
import Analytics from './modules/analytics';
|
||||||
import Crash from './modules/crash';
|
import Crash from './modules/crash';
|
||||||
|
|
||||||
@ -49,16 +49,16 @@ export default class Firebase {
|
|||||||
|
|
||||||
this._log = new Log('firebase');
|
this._log = new Log('firebase');
|
||||||
|
|
||||||
this._auth = new Auth(this, this.options);
|
|
||||||
if (this.options.errorOnMissingPlayServices && !this.googleApiAvailability.isAvailable) {
|
if (this.options.errorOnMissingPlayServices && !this.googleApiAvailability.isAvailable) {
|
||||||
throw new Error(`Google Play Services is required to run this application but no valid installation was found (Code ${this.googleApiAvailability.status}).`);
|
throw new Error(`Google Play Services is required to run this application but no valid installation was found (Code ${this.googleApiAvailability.status}).`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.auth = this._staticsOrInstance('auth', StorageStatics, Auth);
|
this.auth = this._staticsOrInstance('auth', AuthStatics, Auth);
|
||||||
this.storage = this._staticsOrInstance('storage', StorageStatics, Storage);
|
this.storage = this._staticsOrInstance('storage', StorageStatics, Storage);
|
||||||
this.database = this._staticsOrInstance('database', DatabaseStatics, Database);
|
this.database = this._staticsOrInstance('database', DatabaseStatics, Database);
|
||||||
|
this.messaging = this._staticsOrInstance('messaging', MessagingStatics, Messaging);
|
||||||
|
|
||||||
// init auth to stat listeners
|
// init auth to start listeners
|
||||||
this.auth();
|
this.auth();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,13 +92,6 @@ export default class Firebase {
|
|||||||
return this._analytics;
|
return this._analytics;
|
||||||
}
|
}
|
||||||
|
|
||||||
messaging() {
|
|
||||||
if (!this._messaging) {
|
|
||||||
this._messaging = new Messaging(this);
|
|
||||||
}
|
|
||||||
return this._messaging;
|
|
||||||
}
|
|
||||||
|
|
||||||
crash() {
|
crash() {
|
||||||
if (!this._crash) {
|
if (!this._crash) {
|
||||||
this._crash = new Crash(this);
|
this._crash = new Crash(this);
|
||||||
@ -146,7 +139,6 @@ export default class Firebase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Object.assign(getInstance, statics || {});
|
Object.assign(getInstance, statics || {});
|
||||||
|
|
||||||
return getInstance;
|
return getInstance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
80
lib/modules/messaging/RemoteMessage.js
Normal file
80
lib/modules/messaging/RemoteMessage.js
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import { isObject, generatePushID } from './../../utils';
|
||||||
|
|
||||||
|
export default class RemoteMessage {
|
||||||
|
constructor(sender: String) {
|
||||||
|
this.properties = {
|
||||||
|
id: generatePushID(),
|
||||||
|
ttl: 3600,
|
||||||
|
// add the googleapis sender id part if not already added.
|
||||||
|
sender: sender.includes('@') ? sender : `${sender}@gcm.googleapis.com`,
|
||||||
|
type: 'remote',
|
||||||
|
data: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param ttl
|
||||||
|
* @returns {RemoteMessage}
|
||||||
|
*/
|
||||||
|
setTtl(ttl: Number): RemoteMessage {
|
||||||
|
this.properties.ttl = ttl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
setId(id: string): RemoteMessage {
|
||||||
|
this.properties.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @returns {RemoteMessage}
|
||||||
|
*/
|
||||||
|
setType(type: string): RemoteMessage {
|
||||||
|
this.properties.type = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @returns {RemoteMessage}
|
||||||
|
*/
|
||||||
|
setCollapseKey(key: string): RemoteMessage {
|
||||||
|
this.properties.collapseKey = key;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* @returns {RemoteMessage}
|
||||||
|
*/
|
||||||
|
setData(data: Object = {}) {
|
||||||
|
if (!isObject(data)) {
|
||||||
|
throw new Error(`RemoteMessage:setData expects an object as the first parameter but got type '${typeof data}'.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = Object.keys(data);
|
||||||
|
|
||||||
|
// coerce all property values to strings as
|
||||||
|
// remote message data only supports strings
|
||||||
|
for (let i = 0, len = props.length; i < len; i++) {
|
||||||
|
const prop = props[i];
|
||||||
|
this.properties.data[prop] = `${data[prop]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON() {
|
||||||
|
return Object.assign({}, this.properties);
|
||||||
|
}
|
||||||
|
}
|
@ -1,40 +1,32 @@
|
|||||||
import { NativeModules, DeviceEventEmitter, Platform } from 'react-native';
|
import { NativeModules, DeviceEventEmitter, Platform } from 'react-native';
|
||||||
import { Base } from './../base';
|
import { Base } from './../base';
|
||||||
|
import RemoteMessage from './RemoteMessage';
|
||||||
|
|
||||||
const FirebaseMessaging = NativeModules.RNFirebaseMessaging;
|
const FirebaseMessaging = NativeModules.RNFirebaseMessaging;
|
||||||
|
|
||||||
export const EVENT_TYPE = {
|
const EVENT_TYPE = {
|
||||||
RefreshToken: 'FCMTokenRefreshed',
|
RefreshToken: 'FCMTokenRefreshed',
|
||||||
Notification: 'FCMNotificationReceived',
|
Notification: 'FCMNotificationReceived',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NOTIFICATION_TYPE = {
|
const NOTIFICATION_TYPE = {
|
||||||
Remote: 'remote_notification',
|
Remote: 'remote_notification',
|
||||||
NotificationResponse: 'notification_response',
|
NotificationResponse: 'notification_response',
|
||||||
WillPresent: 'will_present_notification',
|
WillPresent: 'will_present_notification',
|
||||||
Local: 'local_notification',
|
Local: 'local_notification',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const REMOTE_NOTIFICATION_RESULT = {
|
const REMOTE_NOTIFICATION_RESULT = {
|
||||||
NewData: 'UIBackgroundFetchResultNewData',
|
NewData: 'UIBackgroundFetchResultNewData',
|
||||||
NoData: 'UIBackgroundFetchResultNoData',
|
NoData: 'UIBackgroundFetchResultNoData',
|
||||||
ResultFailed: 'UIBackgroundFetchResultFailed',
|
ResultFailed: 'UIBackgroundFetchResultFailed',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WILL_PRESENT_RESULT = {
|
const WILL_PRESENT_RESULT = {
|
||||||
All: 'UNNotificationPresentationOptionAll',
|
All: 'UNNotificationPresentationOptionAll',
|
||||||
None: 'UNNotificationPresentationOptionNone',
|
None: 'UNNotificationPresentationOptionNone',
|
||||||
};
|
};
|
||||||
|
|
||||||
type RemoteMessage = {
|
|
||||||
id: string,
|
|
||||||
type: string,
|
|
||||||
ttl?: number,
|
|
||||||
sender: string,
|
|
||||||
collapseKey?: string,
|
|
||||||
data: Object,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IOS only finish function
|
* IOS only finish function
|
||||||
* @param data
|
* @param data
|
||||||
@ -246,10 +238,21 @@ export default class Messaging extends Base {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Send an upstream message
|
* Send an upstream message
|
||||||
* @param senderId
|
* @param remoteMessage
|
||||||
* @param payload
|
|
||||||
*/
|
*/
|
||||||
send(senderId, payload: RemoteMessage) {
|
send(remoteMessage: RemoteMessage) {
|
||||||
return FirebaseMessaging.send(senderId, payload);
|
if (!(remoteMessage instanceof RemoteMessage)) {
|
||||||
|
throw new Error('messaging().send requires an instance of RemoteMessage as the first argument.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return FirebaseMessaging.send(remoteMessage.toJSON());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const statics = {
|
||||||
|
EVENT_TYPE,
|
||||||
|
NOTIFICATION_TYPE,
|
||||||
|
REMOTE_NOTIFICATION_RESULT,
|
||||||
|
WILL_PRESENT_RESULT,
|
||||||
|
RemoteMessage,
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user