[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
|
||||
public void send(String senderId, ReadableMap payload) throws Exception {
|
||||
public void send(ReadableMap remoteMessage) {
|
||||
FirebaseMessaging fm = FirebaseMessaging.getInstance();
|
||||
RemoteMessage.Builder message = new RemoteMessage.Builder(senderId + "@gcm.googleapis.com")
|
||||
.setMessageId(UUID.randomUUID().toString());
|
||||
RemoteMessage.Builder message = new RemoteMessage.Builder(remoteMessage.getString("sender"));
|
||||
|
||||
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()) {
|
||||
String key = iterator.nextKey();
|
||||
String value = getStringFromReadableMap(payload, key);
|
||||
String value = data.getString(key);
|
||||
message.addData(key, value);
|
||||
}
|
||||
fm.send(message.build());
|
||||
}
|
||||
|
||||
private String getStringFromReadableMap(ReadableMap map, String key) throws Exception {
|
||||
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);
|
||||
}
|
||||
fm.send(message.build());
|
||||
}
|
||||
|
||||
private void registerMessageHandler() {
|
||||
|
@ -278,12 +278,12 @@ RCT_EXPORT_METHOD(requestPermissions:(RCTPromiseResolveBlock)resolve rejecter:(R
|
||||
[[UNUserNotificationCenter currentNotificationCenter]
|
||||
requestAuthorizationWithOptions:authOptions
|
||||
completionHandler:^(BOOL granted, NSError * _Nullable error) {
|
||||
resolve(@{@"granted":@(granted)});
|
||||
resolve(@{@"granted":@(granted)});
|
||||
}
|
||||
];
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
||||
}
|
||||
|
||||
@ -408,23 +408,12 @@ RCT_EXPORT_METHOD(getBadgeNumber: (RCTPromiseResolveBlock)resolve rejecter:(RCTP
|
||||
resolve(@([RCTSharedApplication() applicationIconBadgeNumber]));
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(send:(NSString*)senderId withPayload:(NSDictionary *)message)
|
||||
{
|
||||
NSMutableDictionary * mMessage = [message mutableCopy];
|
||||
NSMutableDictionary * upstreamMessage = [[NSMutableDictionary alloc] init];
|
||||
for (NSString* key in mMessage) {
|
||||
upstreamMessage[key] = [NSString stringWithFormat:@"%@", [mMessage valueForKey:key]];
|
||||
}
|
||||
|
||||
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(send:(NSDictionary *)remoteMessage) {
|
||||
int64_t ttl = @([[remoteMessage valueForKey:@"ttl"] intValue]).doubleValue;
|
||||
NSString * mId = [[remoteMessage valueForKey:@"id"] stringValue];
|
||||
NSString * receiver = [[remoteMessage valueForKey:@"senderId"] stringValue];
|
||||
NSDictionary * data = [[remoteMessage valueForKey:@"data"] dictionaryRepresentation];
|
||||
[[FIRMessaging messaging]sendMessage:data to:receiver withMessageID:mId timeToLive:ttl];
|
||||
}
|
||||
|
||||
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 Storage, { statics as StorageStatics } from './modules/storage';
|
||||
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 Crash from './modules/crash';
|
||||
|
||||
@ -49,16 +49,16 @@ export default class Firebase {
|
||||
|
||||
this._log = new Log('firebase');
|
||||
|
||||
this._auth = new Auth(this, this.options);
|
||||
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}).`);
|
||||
}
|
||||
|
||||
this.auth = this._staticsOrInstance('auth', StorageStatics, Auth);
|
||||
this.auth = this._staticsOrInstance('auth', AuthStatics, Auth);
|
||||
this.storage = this._staticsOrInstance('storage', StorageStatics, Storage);
|
||||
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();
|
||||
}
|
||||
|
||||
@ -92,13 +92,6 @@ export default class Firebase {
|
||||
return this._analytics;
|
||||
}
|
||||
|
||||
messaging() {
|
||||
if (!this._messaging) {
|
||||
this._messaging = new Messaging(this);
|
||||
}
|
||||
return this._messaging;
|
||||
}
|
||||
|
||||
crash() {
|
||||
if (!this._crash) {
|
||||
this._crash = new Crash(this);
|
||||
@ -146,7 +139,6 @@ export default class Firebase {
|
||||
};
|
||||
|
||||
Object.assign(getInstance, statics || {});
|
||||
|
||||
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 { Base } from './../base';
|
||||
import RemoteMessage from './RemoteMessage';
|
||||
|
||||
const FirebaseMessaging = NativeModules.RNFirebaseMessaging;
|
||||
|
||||
export const EVENT_TYPE = {
|
||||
const EVENT_TYPE = {
|
||||
RefreshToken: 'FCMTokenRefreshed',
|
||||
Notification: 'FCMNotificationReceived',
|
||||
};
|
||||
|
||||
export const NOTIFICATION_TYPE = {
|
||||
const NOTIFICATION_TYPE = {
|
||||
Remote: 'remote_notification',
|
||||
NotificationResponse: 'notification_response',
|
||||
WillPresent: 'will_present_notification',
|
||||
Local: 'local_notification',
|
||||
};
|
||||
|
||||
export const REMOTE_NOTIFICATION_RESULT = {
|
||||
const REMOTE_NOTIFICATION_RESULT = {
|
||||
NewData: 'UIBackgroundFetchResultNewData',
|
||||
NoData: 'UIBackgroundFetchResultNoData',
|
||||
ResultFailed: 'UIBackgroundFetchResultFailed',
|
||||
};
|
||||
|
||||
export const WILL_PRESENT_RESULT = {
|
||||
const WILL_PRESENT_RESULT = {
|
||||
All: 'UNNotificationPresentationOptionAll',
|
||||
None: 'UNNotificationPresentationOptionNone',
|
||||
};
|
||||
|
||||
type RemoteMessage = {
|
||||
id: string,
|
||||
type: string,
|
||||
ttl?: number,
|
||||
sender: string,
|
||||
collapseKey?: string,
|
||||
data: Object,
|
||||
};
|
||||
|
||||
/**
|
||||
* IOS only finish function
|
||||
* @param data
|
||||
@ -246,10 +238,21 @@ export default class Messaging extends Base {
|
||||
|
||||
/**
|
||||
* Send an upstream message
|
||||
* @param senderId
|
||||
* @param payload
|
||||
* @param remoteMessage
|
||||
*/
|
||||
send(senderId, payload: RemoteMessage) {
|
||||
return FirebaseMessaging.send(senderId, payload);
|
||||
send(remoteMessage: RemoteMessage) {
|
||||
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