diff --git a/RCTRealtimeMessaging/AppDelegate+RealtimeRCTPushNotifications.h b/RCTRealtimeMessaging/AppDelegate+RealtimeRCTPushNotifications.h new file mode 100644 index 0000000..8c2f483 --- /dev/null +++ b/RCTRealtimeMessaging/AppDelegate+RealtimeRCTPushNotifications.h @@ -0,0 +1,17 @@ +// +// AppDelegate+RealtimeRCTPushNotifications.h +// RCTRealtimeMessaging +// +// Created by Joao Caixinha on 07/09/15. +// Copyright (c) 2015 Realtime. All rights reserved. +// +#import "AppDelegate.h" + + +@interface AppDelegate (RealtimeRCTPushNotifications) + +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo; + +@end diff --git a/RCTRealtimeMessaging/AppDelegate+RealtimeRCTPushNotifications.m b/RCTRealtimeMessaging/AppDelegate+RealtimeRCTPushNotifications.m new file mode 100644 index 0000000..14bf25d --- /dev/null +++ b/RCTRealtimeMessaging/AppDelegate+RealtimeRCTPushNotifications.m @@ -0,0 +1,81 @@ +// +// AppDelegate+RealtimeRCTPushNotifications.m +// RCTRealtimeMessaging +// +// Created by Joao Caixinha on 07/09/15. +// Copyright (c) 2015 Realtime. All rights reserved. +// + +#import "AppDelegate+RealtimeRCTPushNotifications.h" +#import + +#pragma GCC diagnostic ignored "-Wundeclared-selector" +@implementation AppDelegate (RealtimeRCTPushNotifications) + + ++ (void)load +{ + [[NSNotificationCenter defaultCenter] addObserver:[self class] selector:@selector(registForNotifications) name:UIApplicationDidFinishLaunchingNotification object:nil]; +} + + ++ (BOOL)registForNotifications +{ +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) { + UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]; + [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; + [[UIApplication sharedApplication] registerForRemoteNotifications]; + } else { + [[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge]; + } +#else + [application registerForRemoteNotificationTypes: UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge]; +#endif + + return YES; +} + + + +- (void)application:(UIApplication *)application +didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken +{ + NSString* newToken = [deviceToken description]; + newToken = [newToken stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]; + newToken = [newToken stringByReplacingOccurrencesOfString:@" " withString:@""]; + NSLog(@"\n\n - didRegisterForRemoteNotificationsWithDeviceToken:\n%@\n", deviceToken); + + id ortc = NSClassFromString (@"OrtcClient"); + if ([ortc respondsToSelector:@selector(setDEVICE_TOKEN:)]) { + [ortc performSelector:@selector(setDEVICE_TOKEN:) withObject:[[NSString alloc] initWithString:newToken]]; + } +} + + +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler +{ + [self application:application didReceiveRemoteNotification:userInfo]; + completionHandler(UIBackgroundFetchResultNewData); +} + +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo +{ + if ([userInfo objectForKey:@"C"] && [userInfo objectForKey:@"M"] && [userInfo objectForKey:@"A"]) { + [[NSNotificationCenter defaultCenter] postNotificationName:@"ApnsNotification" object:nil userInfo:userInfo]; + } +} + + +- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error +{ + NSLog(@"Failed to register with error : %@", error); + + [[NSNotificationCenter defaultCenter] postNotificationName:@"ApnsRegisterError" object:nil userInfo:[NSDictionary dictionaryWithObject:error forKey:@"ApnsRegisterError"]]; +} + + + + + +@end diff --git a/RCTRealtimeMessaging/OrtcClient.m b/RCTRealtimeMessaging/OrtcClient.m index 88a0f8d..24025c1 100644 --- a/RCTRealtimeMessaging/OrtcClient.m +++ b/RCTRealtimeMessaging/OrtcClient.m @@ -1684,8 +1684,7 @@ - (id)initWithConfig:(id) aDelegate - (void) receivedNotification:(NSNotification *) notification { // [notification name] should be @"ApnsNotification" for received Apns Notififications - if ([[notification name] isEqualToString:@"ApnsNotification"]) { - + if ([[notification name] isEqualToString:@"ApnsNotification"]) { NSDictionary *notificaionInfo = [[NSDictionary alloc] initWithDictionary:[notification userInfo]]; if ([[notificaionInfo objectForKey:@"A"] isEqualToString:applicationKey]) { diff --git a/RCTRealtimeMessaging/RCTRealtimeMessaging.h b/RCTRealtimeMessaging/RCTRealtimeMessaging.h index 0405656..f78af68 100644 --- a/RCTRealtimeMessaging/RCTRealtimeMessaging.h +++ b/RCTRealtimeMessaging/RCTRealtimeMessaging.h @@ -15,4 +15,6 @@ @interface RCTRealtimeMessaging : NSObject @property(retain, nonatomic)OrtcClient *ortcClient; @property(retain, nonatomic)NSMutableDictionary *queue; +@property(retain, nonatomic)NSDictionary *pushInfo; + @end diff --git a/RCTRealtimeMessaging/RCTRealtimeMessaging.m b/RCTRealtimeMessaging/RCTRealtimeMessaging.m index f9468af..1e6810e 100644 --- a/RCTRealtimeMessaging/RCTRealtimeMessaging.m +++ b/RCTRealtimeMessaging/RCTRealtimeMessaging.m @@ -14,6 +14,82 @@ @implementation RCTRealtimeMessaging RCT_EXPORT_MODULE() + +- (id)init{ + self = [super init]; + if (self) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedNotification:) name:@"Notification" object:nil]; + } + return self; +} + +- (void)dealloc{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void) receivedNotification:(NSNotification *) notification{ + NSDictionary *userInfo = [notification userInfo]; + NSMutableDictionary *pushInfo = [[NSMutableDictionary alloc] init]; + [self handleCustom:pushInfo from:userInfo]; + _pushInfo = [pushInfo objectForKey:@"payload"]; + [self.bridge.eventDispatcher sendDeviceEventWithName:@"onPushNotification" + body:[pushInfo objectForKey:@"payload"]]; +} + +RCT_EXPORT_METHOD(checkForNotifications){ + if(_pushInfo){ + [self.bridge.eventDispatcher sendDeviceEventWithName:@"onPushNotification" + body:_pushInfo]; + _pushInfo = nil; + } +} + + +- (void)handleStd:(NSMutableDictionary*)pushInfo from:(NSDictionary*)userInfo +{ + NSString* msg = [userInfo objectForKey:@"M"]; + int num = 0; + NSUInteger len = [msg length]; + unichar buffer[len+1]; + [msg getCharacters: buffer range: NSMakeRange(0, len)]; + + NSString *finalM; + for (int i=0; i i + 1) { + finalM = [msg substringFromIndex:i+1]; + } + } + } + + NSError *error = nil; + NSData *jsonData = [finalM dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error]; + + if (json != nil) { + [pushInfo setObject:json forKey:@"payload"]; + }else + { + [pushInfo setObject:finalM forKey:@"payload"]; + } +} + + +- (void)handleCustom:(NSMutableDictionary*)pushInfo from:(NSDictionary*)userInfo +{ + NSMutableDictionary *payload = [[NSMutableDictionary alloc] init]; + for (NSString* key in [[userInfo objectForKey:@"aps"] allKeys]) { + if (![key isEqualToString:@"sound"] && ![key isEqualToString:@"badge"] && ![key isEqualToString:@"alert"]) { + [payload setObject:[[userInfo objectForKey:@"aps"] objectForKey:key] forKey:key]; + } + } + [pushInfo setObject:payload forKey:@"payload"]; +} + + + + RCT_EXPORT_METHOD(connect:(id)connectionSettings id:(NSString*)pId){ NSString *appKey = [RCTConvert NSString:connectionSettings[@"appKey"]]; diff --git a/RCTRealtimeMessaging/RealtimePushAppDelegate.h b/RCTRealtimeMessaging/RealtimePushAppDelegate.h deleted file mode 100644 index b8b1c40..0000000 --- a/RCTRealtimeMessaging/RealtimePushAppDelegate.h +++ /dev/null @@ -1,84 +0,0 @@ -// -// AppDelegate.h -// OrtcClient -// -// Created by iOSdev on 9/20/13. -// Copyright (c) 2013 Realtime.co All rights reserved. -// -#import -#define NOTIFICATIONS_KEY @"Local_Storage_Notifications" - -/** - This class manages the Apple Push Notifications Service - - __Discussion__ - - This Class inherits from the UIResponder class. UIResponder defines an interface for objects that respond to and handle events, is the superclass of UIApplication. - - RealtimePushAppDelegate implements UIApplicationDelegate protocol. - - In order to use OrtcClient with Apple Push Notifications Service, your Application Delegate must inherit from RealtimePushAppDelegate, you will also need in `application:didFinishLaunchingWithOptions:` implementation call his super. - - This class enables use of push notifications as well as forwards your messages to OrtcClient. - - Just chek the example code: - - - in your Application delegate (interface) - -

- @interface YOUR_APPLICATION_DELEGATE : RealtimePushAppDelegate
- ...
- @end
- 
- 
- - - - in your Application delegate (implementation) -

- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
-    [super application:application didFinishLaunchingWithOptions:launchOptions];
-    
-    // the following code is standard template code
-    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
-    // Override point for customization after application launch.
-    self.window.backgroundColor = [UIColor whiteColor];
-    [self.window makeKeyAndVisible];
-    return YES;
- }
-
- 
- - - -If for some reason, in your Application delegate, You implement: - - ``- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo`` - - You must implement his super in order to get OrtcClient functionalities. - - - - - __See Also:__ - - [_UIApplication Documentaion_](http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplication\_Class/index.html) - - [_UIApplicationDelegate Documentaion_](https://developer.apple.com/library/ios/documentation/uikit/reference/UIApplication\_Class/Reference/Reference.html) - - */ - -@interface RealtimePushAppDelegate : UIResponder - -///--------------------------------------------------------------------------------------- -/// @name Properties -///--------------------------------------------------------------------------------------- -/** - The window to use when presenting a storyboard. - - This property contains the window used to present the app’s visual content on the device’s main screen. -*/ -@property (strong, nonatomic) UIWindow *window; - -@end - diff --git a/RCTRealtimeMessaging/RealtimePushAppDelegate.m b/RCTRealtimeMessaging/RealtimePushAppDelegate.m deleted file mode 100644 index 842040c..0000000 --- a/RCTRealtimeMessaging/RealtimePushAppDelegate.m +++ /dev/null @@ -1,93 +0,0 @@ -// -// AppDelegate.m -// OrtcClient -// -// Created by iOSdev on 9/20/13. -// Copyright (c) 2013 Realtime.co All rights reserved. -// - -#import "RealtimePushAppDelegate.h" -#import "OrtcClient.h" - -@implementation RealtimePushAppDelegate -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 - if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) { - UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]; - [application registerUserNotificationSettings:settings]; - [application registerForRemoteNotifications]; - } else { - [application registerForRemoteNotificationTypes: UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge]; - - } -#else - [application registerForRemoteNotificationTypes: UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge]; -#endif - - return YES; -} -#pragma clang diagnostic pop - -- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken { - - NSString* newToken = [deviceToken description]; - newToken = [newToken stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]; - newToken = [newToken stringByReplacingOccurrencesOfString:@" " withString:@""]; - NSLog(@"\n\n - didRegisterForRemoteNotificationsWithDeviceToken:\n%@\n", deviceToken); - - [OrtcClient performSelector:@selector(setDEVICE_TOKEN:) withObject:[[NSString alloc] initWithString:newToken]]; -} - - -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler -{ - [self application:application didReceiveRemoteNotification:userInfo]; -} - -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { - - //NSLog(@"\n\n - didReceiveRemoteNotification:\n%@\n", userInfo); - - // Handle the notification here - //clear notifications - //[[UIApplication sharedApplication] cancelAllLocalNotifications]; - - // set application badge number - //[[UIApplication sharedApplication] setApplicationIconBadgeNumber:1]; - - /* - if (application.applicationState != UIApplicationStateActive) { - // app was just brought from background to foreground - } - */ - - // Write to NSUserDefaults - if ([userInfo objectForKey:@"C"] && [userInfo objectForKey:@"M"] && [userInfo objectForKey:@"A"]) { - - NSString *ortcMessage = [NSString stringWithFormat:@"a[\"{\\\"ch\\\":\\\"%@\\\",\\\"m\\\":\\\"%@\\\"}\"]", [userInfo objectForKey:@"C"], [userInfo objectForKey:@"M"]]; - - NSMutableDictionary *notificationsDict = [[NSMutableDictionary alloc] initWithDictionary:[[NSUserDefaults standardUserDefaults] objectForKey:NOTIFICATIONS_KEY]]; - NSMutableArray *notificationsArray = [[NSMutableArray alloc] initWithArray:[notificationsDict objectForKey:[userInfo objectForKey:@"A"]]]; - [notificationsArray addObject:ortcMessage]; - [notificationsDict setObject:notificationsArray forKey:[userInfo objectForKey:@"A"]]; - - [[NSUserDefaults standardUserDefaults] setObject:notificationsDict forKey:NOTIFICATIONS_KEY]; - [[NSUserDefaults standardUserDefaults] synchronize]; - - [[NSNotificationCenter defaultCenter] postNotificationName:@"ApnsNotification" object:nil userInfo:userInfo]; - } -} - - -- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error -{ - NSLog(@"Failed to register with error : %@", error); - - [[NSNotificationCenter defaultCenter] postNotificationName:@"ApnsRegisterError" object:nil userInfo:[NSDictionary dictionaryWithObject:error forKey:@"ApnsRegisterError"]]; -} - - -@end diff --git a/RCTRealtimeMessagingIOS.js b/RCTRealtimeMessagingIOS.js index f2cb522..26a0dc0 100644 --- a/RCTRealtimeMessagingIOS.js +++ b/RCTRealtimeMessagingIOS.js @@ -38,7 +38,7 @@ class RCTRealtimeMessagingIOS extends React.Component { } RTSubscribeWithNotifications(channel, subscribeOnReconnect: boolean){ - ortcClient.subscribe(channel, subscribeOnReconnect, this.id); + ortcClient.subscribeWithNotifications(channel, subscribeOnReconnect, this.id); } RTUnsubscribe(channel){ @@ -112,6 +112,15 @@ class RCTRealtimeMessagingIOS extends React.Component { - onEnablePresence */ + RTCustomPushNotificationListener(callBack: Function){ + require('RCTDeviceEventEmitter').addListener( + 'onPushNotification', + callBack + ); + ortcClient.checkForNotifications(); + }; + + RTEventListener(notification, callBack: Function){ var modNotification = String(this.id) + '-' + notification; var channelExists = RTEvents[modNotification]; diff --git a/README.md b/README.md index 5601e97..360185e 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,42 @@ RTRemoveEventListener removes an event registration. After this method when the - On success -> `{"result": result}` - On error -> `{"error": error}` +###Push notification handling ( available from 1.0.6 ) + +####Configure your project for push notifications handling + +To configure your react-native project to receive push notifications you must follow [this guide](http://messaging-public.realtime.co/documentation/starting-guide/mobilePushAPNS.html) for the iOS platform. +After this process you must drag AppDelegate+RealtimeRCTPushNotifications(.m, .h) category from RCTRealtimeMessaging plugin folder to your project, where AppDelegate class is, and you are ready to go. + +####Handling automatic push notifications through javascript + +To receive push notifications in a RealtimeMessaging channel you must use the SubscribeWithNotifications method. The onMessage event listener will be the only entry point for automatic push notifications(sent using a Realtime client send method), so when the application starts you must connect and subscribe the channels for handling that type of notifications. + +***Example:*** + + RCTRealtimeMessaging.RTSubscribeWithNotifications(this.state.channel, true); + RCTRealtimeMessaging.RTEventListener("onMessage",this._onMessage), + _onMessage: function(messageEvent) + { + this._log("Received message or automatic notification: ["+messageEvent.message+"] on channel ["+ messageEvent.channel+"]"); + }, + +####Handling custom push notifications through javascript + +For handling custom push notifications ( sent using the Realtime mobile push notifications REST API) we added the following event listener: + +* RTCustomPushNotificationListener(callBack: Function) + +***Example:*** + + componentDidMount: function(){ + RCTRealtimeMessaging.RTCustomPushNotificationListener(this._onNotification); + }, + _onNotification: function(data) + { + this._log("Received notification: " + JSON.stringify(data)); + }, ---------- diff --git a/package.json b/package.json index 64cf718..e3715ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-realtimemessaging-ios", - "version": "1.0.5", + "version": "1.0.6", "description": "The Realtime Framework Cloud Messaging Pub/Sub client for React-Native", "main": "RCTRealtimeMessagingIOS.js", "scripts": {