Commit cecf7a60 authored by Libin Lu's avatar Libin Lu

ios v4

parent 60d941f6
...@@ -56,6 +56,16 @@ export default class PushController extends Component { ...@@ -56,6 +56,16 @@ export default class PushController extends Component {
console.log("TOKEN (refreshUnsubscribe)", token); console.log("TOKEN (refreshUnsubscribe)", token);
this.props.onChangeToken(token); this.props.onChangeToken(token);
}); });
// direct channel related methods are ios only
// directly channel is truned off in iOS by default, this method enables it
FCM.enableDirectChannel();
this.channelConnectionListener = FCM.on(FCMEvent.DirectChannelConnectionChanged, (data) => {
console.log('direct channel connected' + data);
});
setTimeout(function() {
FCM.isDirectChannelEstablished().then(d => console.log(d));
}, 1000);
} }
showLocalNotification(notif) { showLocalNotification(notif) {
......
declare module "react-native-fcm" { declare module "react-native-fcm" {
type FCMEventType = "FCMTokenRefreshed" | "FCMNotificationReceived"; type FCMEventType = "FCMTokenRefreshed" | "FCMNotificationReceived" | 'FCMDirectChannelConnectionChanged';
export module FCMEvent { export module FCMEvent {
const RefreshToken = "FCMTokenRefreshed"; const RefreshToken = "FCMTokenRefreshed";
const Notification = "FCMNotificationReceived"; const Notification = "FCMNotificationReceived";
const DirectChannelConnectionChanged: 'FCMDirectChannelConnectionChanged'
} }
export module RemoteNotificationResult { export module RemoteNotificationResult {
...@@ -79,6 +80,10 @@ declare module "react-native-fcm" { ...@@ -79,6 +80,10 @@ declare module "react-native-fcm" {
static setBadgeNumber(badge: number): void; static setBadgeNumber(badge: number): void;
static getBadgeNumber(): Promise<number>; static getBadgeNumber(): Promise<number>;
static send(id: string, data: any): void; static send(id: string, data: any): void;
static enableDirectChannel(): void
static isDirectChannelEstablished(): Promise<boolean>
static getAPNSToken(): Promise<string>
} }
export default FCM; export default FCM;
......
import {NativeModules, DeviceEventEmitter, Platform} from 'react-native'; import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
const EventEmitter = new NativeEventEmitter(NativeModules.RNFIRMessaging);
export const FCMEvent = { export const FCMEvent = {
RefreshToken: 'FCMTokenRefreshed', RefreshToken: 'FCMTokenRefreshed',
Notification: 'FCMNotificationReceived' Notification: 'FCMNotificationReceived',
} DirectChannelConnectionChanged: 'FCMDirectChannelConnectionChanged'
};
export const RemoteNotificationResult = { export const RemoteNotificationResult = {
NewData: 'UIBackgroundFetchResultNewData', NewData: 'UIBackgroundFetchResultNewData',
NoData: 'UIBackgroundFetchResultNoData', NoData: 'UIBackgroundFetchResultNoData',
ResultFailed: 'UIBackgroundFetchResultFailed' ResultFailed: 'UIBackgroundFetchResultFailed'
} };
export const WillPresentNotificationResult = { export const WillPresentNotificationResult = {
All: 'UNNotificationPresentationOptionAll', All: 'UNNotificationPresentationOptionAll',
None: 'UNNotificationPresentationOptionNone' None: 'UNNotificationPresentationOptionNone'
} };
export const NotificationType = { export const NotificationType = {
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'
} };
const RNFIRMessaging = NativeModules.RNFIRMessaging; const RNFIRMessaging = NativeModules.RNFIRMessaging;
...@@ -29,28 +32,41 @@ const FCM = {}; ...@@ -29,28 +32,41 @@ const FCM = {};
FCM.getInitialNotification = () => { FCM.getInitialNotification = () => {
return RNFIRMessaging.getInitialNotification(); return RNFIRMessaging.getInitialNotification();
} };
FCM.enableDirectChannel = () => {
if (Platform.OS === 'ios') {
return RNFIRMessaging.enableDirectChannel();
}
};
FCM.isDirectChannelEstablished = () => {
return Platform.OS === 'ios' ? RNFIRMessaging.isDirectChannelEstablished() : Promise.resolve(true);
};
FCM.getFCMToken = () => { FCM.getFCMToken = () => {
return RNFIRMessaging.getFCMToken(); return RNFIRMessaging.getFCMToken();
}; };
FCM.getAPNSToken = () => {
if (Platform.OS === 'ios') {
return RNFIRMessaging.getAPNSToken();
}
};
FCM.requestPermissions = () => { FCM.requestPermissions = () => {
return RNFIRMessaging.requestPermissions(); return RNFIRMessaging.requestPermissions();
}; };
FCM.presentLocalNotification = (details) => { FCM.presentLocalNotification = (details) => {
details.id = details.id || new Date().getTime().toString() details.id = details.id || new Date().getTime().toString();
details.local_notification = true; details.local_notification = true;
RNFIRMessaging.presentLocalNotification(details); RNFIRMessaging.presentLocalNotification(details);
}; };
FCM.scheduleLocalNotification = function(details) { FCM.scheduleLocalNotification = function(details) {
if (!details.id) { if (!details.id) {
throw new Error("id is required for scheduled notification"); throw new Error('id is required for scheduled notification');
}
if (!details.fire_date) {
throw new Error("fire_date is required for scheduled notification");
} }
details.local_notification = true; details.local_notification = true;
RNFIRMessaging.scheduleLocalNotification(details); RNFIRMessaging.scheduleLocalNotification(details);
...@@ -61,7 +77,7 @@ FCM.getScheduledLocalNotifications = function() { ...@@ -61,7 +77,7 @@ FCM.getScheduledLocalNotifications = function() {
}; };
FCM.cancelLocalNotification = (notificationID) => { FCM.cancelLocalNotification = (notificationID) => {
if(!notificationID){ if (!notificationID) {
return; return;
} }
RNFIRMessaging.cancelLocalNotification(notificationID); RNFIRMessaging.cancelLocalNotification(notificationID);
...@@ -72,35 +88,34 @@ FCM.cancelAllLocalNotifications = () => { ...@@ -72,35 +88,34 @@ FCM.cancelAllLocalNotifications = () => {
}; };
FCM.removeDeliveredNotification = (notificationID) => { FCM.removeDeliveredNotification = (notificationID) => {
if(!notificationID){ if (!notificationID) {
return; return;
} }
RNFIRMessaging.removeDeliveredNotification(notificationID); RNFIRMessaging.removeDeliveredNotification(notificationID);
} };
FCM.removeAllDeliveredNotifications = () => { FCM.removeAllDeliveredNotifications = () => {
RNFIRMessaging.removeAllDeliveredNotifications(); RNFIRMessaging.removeAllDeliveredNotifications();
} };
FCM.setBadgeNumber = (number) => { FCM.setBadgeNumber = (number) => {
RNFIRMessaging.setBadgeNumber(number); RNFIRMessaging.setBadgeNumber(number);
} };
FCM.getBadgeNumber = () => { FCM.getBadgeNumber = () => {
return RNFIRMessaging.getBadgeNumber(); return RNFIRMessaging.getBadgeNumber();
} };
function finish(result){ function finish(result) {
if(Platform.OS !== 'ios'){ if (Platform.OS !== 'ios') {
return; return;
} }
if(!this._finishCalled && this._completionHandlerId){ if (!this._finishCalled && this._completionHandlerId) {
this._finishCalled = true; this._finishCalled = true;
switch(this._notificationType){ switch (this._notificationType) {
case NotificationType.Remote: case NotificationType.Remote:
result = result || RemoteNotificationResult.NoData; result = result || RemoteNotificationResult.NoData;
if(!Object.values(RemoteNotificationResult).includes(result)){ if (!Object.values(RemoteNotificationResult).includes(result)) {
throw new Error(`Invalid RemoteNotificationResult, use import {RemoteNotificationResult} from 'react-native-fcm' to avoid typo`); throw new Error(`Invalid RemoteNotificationResult, use import {RemoteNotificationResult} from 'react-native-fcm' to avoid typo`);
} }
RNFIRMessaging.finishRemoteNotification(this._completionHandlerId, result); RNFIRMessaging.finishRemoteNotification(this._completionHandlerId, result);
...@@ -110,7 +125,7 @@ function finish(result){ ...@@ -110,7 +125,7 @@ function finish(result){
return; return;
case NotificationType.WillPresent: case NotificationType.WillPresent:
result = result || (this.show_in_foreground ? WillPresentNotificationResult.All : WillPresentNotificationResult.None); result = result || (this.show_in_foreground ? WillPresentNotificationResult.All : WillPresentNotificationResult.None);
if(!Object.values(WillPresentNotificationResult).includes(result)){ if (!Object.values(WillPresentNotificationResult).includes(result)) {
throw new Error(`Invalid WillPresentNotificationResult, make sure you use import {WillPresentNotificationResult} from 'react-native-fcm' to avoid typo`); throw new Error(`Invalid WillPresentNotificationResult, make sure you use import {WillPresentNotificationResult} from 'react-native-fcm' to avoid typo`);
} }
RNFIRMessaging.finishWillPresentNotification(this._completionHandlerId, result); RNFIRMessaging.finishWillPresentNotification(this._completionHandlerId, result);
...@@ -126,16 +141,21 @@ FCM.on = (event, callback) => { ...@@ -126,16 +141,21 @@ FCM.on = (event, callback) => {
throw new Error(`Invalid FCM event subscription, use import {FCMEvent} from 'react-native-fcm' to avoid typo`); throw new Error(`Invalid FCM event subscription, use import {FCMEvent} from 'react-native-fcm' to avoid typo`);
}; };
if(event === FCMEvent.Notification){ if (event === FCMEvent.Notification) {
return DeviceEventEmitter.addListener(event, async(data)=>{ return EventEmitter.addListener(event, async(data) => {
data.finish = finish; data.finish = finish;
try {
await callback(data); await callback(data);
if(!data._finishCalled){ } catch (err) {
console.error('Notification handler err', err);
throw err;
}
if (!data._finishCalled) {
data.finish(); data.finish();
} }
}) });
} }
return DeviceEventEmitter.addListener(event, callback); return EventEmitter.addListener(event, callback);
}; };
FCM.subscribeToTopic = (topic) => { FCM.subscribeToTopic = (topic) => {
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#import <React/RCTUtils.h> #import <React/RCTUtils.h>
@import UserNotifications; @import UserNotifications;
#import <FirebaseInstanceID/FirebaseInstanceID.h>
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
...@@ -17,6 +16,8 @@ ...@@ -17,6 +16,8 @@
#endif #endif
NSString *const FCMNotificationReceived = @"FCMNotificationReceived"; NSString *const FCMNotificationReceived = @"FCMNotificationReceived";
NSString *const FCMTokenRefreshed = @"FCMTokenRefreshed";
NSString *const FCMDirectChannelConnectionChanged = @"FCMDirectChannelConnectionChanged";
@implementation RCTConvert (NSCalendarUnit) @implementation RCTConvert (NSCalendarUnit)
...@@ -135,6 +136,10 @@ RCT_ENUM_CONVERTER(UNNotificationPresentationOptions, (@{ ...@@ -135,6 +136,10 @@ RCT_ENUM_CONVERTER(UNNotificationPresentationOptions, (@{
@synthesize bridge = _bridge; @synthesize bridge = _bridge;
RCT_EXPORT_MODULE(); RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents {
return @[FCMNotificationReceived, FCMTokenRefreshed, FCMDirectChannelConnectionChanged];
}
+ (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull RCTRemoteNotificationCallback)completionHandler { + (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull RCTRemoteNotificationCallback)completionHandler {
NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: userInfo]; NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: userInfo];
[data setValue:@"remote_notification" forKey:@"_notificationType"]; [data setValue:@"remote_notification" forKey:@"_notificationType"];
...@@ -171,28 +176,13 @@ RCT_EXPORT_MODULE(); ...@@ -171,28 +176,13 @@ RCT_EXPORT_MODULE();
[[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self];
} }
- (void)setBridge:(RCTBridge *)bridge - (instancetype)init {
{ self = [super init];
_bridge = bridge;
[[NSNotificationCenter defaultCenter] addObserver:self [[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleNotificationReceived:) selector:@selector(handleNotificationReceived:)
name:FCMNotificationReceived name:FCMNotificationReceived
object:nil]; object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(disconnectFCM)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(connectToFCM)
name:UIApplicationDidBecomeActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(onTokenRefresh)
name:kFIRInstanceIDTokenRefreshNotification object:nil];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(sendDataMessageFailure:) addObserver:self selector:@selector(sendDataMessageFailure:)
name:FIRMessagingSendErrorNotification object:nil]; name:FIRMessagingSendErrorNotification object:nil];
...@@ -201,48 +191,49 @@ RCT_EXPORT_MODULE(); ...@@ -201,48 +191,49 @@ RCT_EXPORT_MODULE();
addObserver:self selector:@selector(sendDataMessageSuccess:) addObserver:self selector:@selector(sendDataMessageSuccess:)
name:FIRMessagingSendSuccessNotification object:nil]; name:FIRMessagingSendSuccessNotification object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(connectionStateChanged:)
name:FIRMessagingConnectionStateChangedNotification object:nil];
// For iOS 10 data message (sent via FCM) // For iOS 10 data message (sent via FCM)
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[[FIRMessaging messaging] setRemoteMessageDelegate:self]; [[FIRMessaging messaging] setDelegate:self];
[self connectToFCM];
}); });
return self;
} }
- (void)connectToFCM RCT_EXPORT_METHOD(enableDirectChannel)
{ {
[[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) { [[FIRMessaging messaging] setShouldEstablishDirectChannel:@YES];
if (error != nil) {
NSLog(@"Unable to connect to FCM. %@", error);
} else {
NSLog(@"Connected to FCM.");
}
}];
} }
- (void)disconnectFCM RCT_EXPORT_METHOD(isDirectChannelEstablished:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{ {
[[FIRMessaging messaging] disconnect]; resolve([[FIRMessaging messaging] isDirectChannelEstablished] ? @YES: @NO);
NSLog(@"Disconnected from FCM");
} }
RCT_EXPORT_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve) RCT_EXPORT_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{ {
UILocalNotification *localUserInfo = _bridge.launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]; UILocalNotification *localUserInfo = _bridge.launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
if (localUserInfo) { if (localUserInfo) {
resolve([[localUserInfo userInfo] copy]); resolve([[localUserInfo userInfo] copy]);
return; } else {
}
resolve([_bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy]); resolve([_bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy]);
}
} }
RCT_EXPORT_METHOD(getFCMToken:(RCTPromiseResolveBlock)resolve) RCT_EXPORT_METHOD(getAPNSToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{ {
resolve([[FIRInstanceID instanceID] token]); resolve([FIRMessaging messaging].APNSToken);
} }
- (void) onTokenRefresh RCT_EXPORT_METHOD(getFCMToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{ {
[self sendEventWithName:@"FCMTokenRefreshed" body:[[FIRInstanceID instanceID] token]]; resolve([FIRMessaging messaging].FCMToken);
}
- (void)messaging:(nonnull FIRMessaging *)messaging didRefreshRegistrationToken:(nonnull NSString *)fcmToken {
[self sendEventWithName:FCMTokenRefreshed body:fcmToken];
} }
RCT_EXPORT_METHOD(requestPermissions:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) RCT_EXPORT_METHOD(requestPermissions:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
...@@ -373,7 +364,7 @@ RCT_EXPORT_METHOD(cancelLocalNotification:(NSString*) notificationId) ...@@ -373,7 +364,7 @@ RCT_EXPORT_METHOD(cancelLocalNotification:(NSString*) notificationId)
} }
} }
RCT_EXPORT_METHOD(getScheduledLocalNotifications:(RCTPromiseResolveBlock)resolve) RCT_EXPORT_METHOD(getScheduledLocalNotifications:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{ {
if([UNUserNotificationCenter currentNotificationCenter] != nil){ if([UNUserNotificationCenter currentNotificationCenter] != nil){
[[UNUserNotificationCenter currentNotificationCenter] getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> * _Nonnull requests) { [[UNUserNotificationCenter currentNotificationCenter] getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> * _Nonnull requests) {
...@@ -398,7 +389,7 @@ RCT_EXPORT_METHOD(setBadgeNumber: (NSInteger*) number) ...@@ -398,7 +389,7 @@ RCT_EXPORT_METHOD(setBadgeNumber: (NSInteger*) number)
[RCTSharedApplication() setApplicationIconBadgeNumber:*number]; [RCTSharedApplication() setApplicationIconBadgeNumber:*number];
} }
RCT_EXPORT_METHOD(getBadgeNumber: (RCTPromiseResolveBlock)resolve) RCT_EXPORT_METHOD(getBadgeNumber: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{ {
resolve(@([RCTSharedApplication() applicationIconBadgeNumber])); resolve(@([RCTSharedApplication() applicationIconBadgeNumber]));
} }
...@@ -484,4 +475,10 @@ RCT_EXPORT_METHOD(finishNotificationResponse: (NSString *)completionHandlerId){ ...@@ -484,4 +475,10 @@ RCT_EXPORT_METHOD(finishNotificationResponse: (NSString *)completionHandlerId){
NSLog(@"sendDataMessageSuccess: %@", messageID); NSLog(@"sendDataMessageSuccess: %@", messageID);
} }
- (void)connectionStateChanged:(NSNotification *)notification
{
[self sendEventWithName:FCMDirectChannelConnectionChanged body:[FIRMessaging messaging].isDirectChannelEstablished ? @YES: @NO];
NSLog(@"connectionStateChanged: %@", [FIRMessaging messaging].isDirectChannelEstablished ? @"connected": @"disconnected");
}
@end @end
...@@ -139,6 +139,7 @@ ...@@ -139,6 +139,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
...@@ -161,6 +162,7 @@ ...@@ -161,6 +162,7 @@
"-Wextra", "-Wextra",
"-Wall", "-Wall",
"-Wno-semicolon-before-method-body", "-Wno-semicolon-before-method-body",
"-Wno-unused-parameter",
); );
}; };
name = Debug; name = Debug;
...@@ -183,6 +185,7 @@ ...@@ -183,6 +185,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES; COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
...@@ -203,6 +206,7 @@ ...@@ -203,6 +206,7 @@
"-Wextra", "-Wextra",
"-Wall", "-Wall",
"-Wno-semicolon-before-method-body", "-Wno-semicolon-before-method-body",
"-Wno-unused-parameter",
); );
}; };
name = Release; name = Release;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<key>RNFIRMessaging.xcscheme</key> <key>RNFIRMessaging.xcscheme</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>7</integer> <integer>4</integer>
</dict> </dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment