From c28bfbb83c4c9302e42d6a94ffc3e89811dec4d1 Mon Sep 17 00:00:00 2001 From: Dimitar Date: Thu, 28 Jan 2016 15:27:52 +0200 Subject: [PATCH 01/12] fix ios9 interactive push notifications in background --- src/ios/AppDelegate+notification.m | 14 ++++- src/ios/PushPlugin.h | 1 + src/ios/PushPlugin.m | 91 +++++++++++++++++++++--------- www/PushNotification.js | 5 ++ 4 files changed, 80 insertions(+), 31 deletions(-) diff --git a/src/ios/AppDelegate+notification.m b/src/ios/AppDelegate+notification.m index c0f122f1..2c2a466e 100644 --- a/src/ios/AppDelegate+notification.m +++ b/src/ios/AppDelegate+notification.m @@ -111,19 +111,27 @@ - (void)application:(UIApplication *) application handleActionWithIdentifier: (N // the notification already contains the category, but the client also needs the identifier (action button) NSMutableDictionary *mutableNotification = [notification mutableCopy]; - [mutableNotification setObject:identifier forKey:@"identifier"]; + NSLog(@"handleActionWithIdentifier"); + if (application.applicationState == UIApplicationStateActive) { PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"]; pushHandler.notificationMessage = mutableNotification; pushHandler.isInline = YES; [pushHandler notificationReceived]; } else { + void (^safeHandler)() = ^(void){ + dispatch_async(dispatch_get_main_queue(), ^{ + completionHandler(); + }); + }; + NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:1]; + [params setObject:safeHandler forKey:@"handler"]; PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"]; pushHandler.notificationMessage = mutableNotification; + pushHandler.params= params; [pushHandler performSelectorOnMainThread:@selector(notificationReceived) withObject:pushHandler waitUntilDone:NO]; } - completionHandler(); } #endif @@ -142,7 +150,7 @@ - (void)setLaunchNotification:(NSDictionary *)aDictionary - (void)dealloc { - self.launchNotification = nil; // clear the association and release the object + self.launchNotification = nil; // clear the association and release the object } @end diff --git a/src/ios/PushPlugin.h b/src/ios/PushPlugin.h index b1ec8ffa..3a191652 100644 --- a/src/ios/PushPlugin.h +++ b/src/ios/PushPlugin.h @@ -41,6 +41,7 @@ @property (nonatomic, copy) NSString *callback; @property (nonatomic, strong) NSDictionary *notificationMessage; +@property (nonatomic, strong) NSMutableDictionary *params; @property BOOL isInline; - (void)register:(CDVInvokedUrlCommand*)command; diff --git a/src/ios/PushPlugin.m b/src/ios/PushPlugin.m index a3a3440e..1451e196 100644 --- a/src/ios/PushPlugin.m +++ b/src/ios/PushPlugin.m @@ -28,6 +28,7 @@ @implementation PushPlugin @synthesize notificationMessage; +@synthesize params; @synthesize isInline; @synthesize callbackId; @@ -342,34 +343,6 @@ - (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error [self failWithMessage:@"" withError:error]; } -- (void)notificationReceived { - NSLog(@"Notification received"); - - if (notificationMessage && self.callback) - { - NSMutableString *jsonStr = [NSMutableString stringWithString:@"{"]; - - [self parseDictionary:notificationMessage intoJSON:jsonStr]; - - if (isInline) - { - [jsonStr appendFormat:@"foreground:\"%d\"", 1]; - isInline = NO; - } - else - [jsonStr appendFormat:@"foreground:\"%d\"", 0]; - - [jsonStr appendString:@"}"]; - - NSLog(@"Msg: %@", jsonStr); - - NSString * jsCallBack = [NSString stringWithFormat:@"%@(%@);", self.callback, jsonStr]; - [self.webView stringByEvaluatingJavaScriptFromString:jsCallBack]; - - self.notificationMessage = nil; - } -} - // reentrant method to drill down and surface all sub-dictionaries' key/value pairs into the top level json -(void)parseDictionary:(NSDictionary *)inDictionary intoJSON:(NSMutableString *)jsonString { @@ -423,4 +396,66 @@ -(void)failWithMessage:(NSString *)message withError:(NSError *)error [self.commandDelegate sendPluginResult:commandResult callbackId:self.callbackId]; } +- (void)notificationReceived { + NSLog(@"Notification received"); + + if (notificationMessage && self.callback) + { + NSMutableString *jsonStr = [NSMutableString stringWithString:@"{"]; + + [self parseDictionary:notificationMessage intoJSON:jsonStr]; + + if (isInline) + { + [jsonStr appendFormat:@"foreground:\"%d\"", 1]; + isInline = NO; + } + else + [jsonStr appendFormat:@"foreground:\"%d\"", 0]; + + [jsonStr appendString:@"}"]; + + NSLog(@"Msg: %@", jsonStr); + + NSString * jsCallBack = [NSString stringWithFormat:@"%@(%@);", self.callback, jsonStr]; + [self.webView performSelectorOnMainThread:@selector(stringByEvaluatingJavaScriptFromString:) withObject:jsCallBack waitUntilDone:NO]; + + self.notificationMessage = nil; + } +} + +-(void) notificationProcessed:(CDVInvokedUrlCommand*)command +{ + NSLog(@"Push Plugin finish called"); + + [self.commandDelegate runInBackground:^ { + UIApplication *app = [UIApplication sharedApplication]; + float finishTimer = (app.backgroundTimeRemaining > 20.0) ? 20.0 : app.backgroundTimeRemaining; + + dispatch_async(dispatch_get_main_queue(), ^{ + [NSTimer scheduledTimerWithTimeInterval:finishTimer + target:self + selector:@selector(stopBackgroundTask:) + userInfo:nil + repeats:NO]; + }); + }]; +} + +-(void)stopBackgroundTask:(NSTimer*)timer +{ + UIApplication *app = [UIApplication sharedApplication]; + + NSLog(@"Push Plugin stopBackgroundTask called"); + + if (self.params) { + void (^_completionHandler)() = self.params[@"handler"]; + if (_completionHandler) { + NSLog(@"Push Plugin: stopBackgroundTask (remaining t: %f)", app.backgroundTimeRemaining); + _completionHandler(); + _completionHandler = nil; + } + } +} + @end diff --git a/www/PushNotification.js b/www/PushNotification.js index 15e247ce..3f0babf9 100644 --- a/www/PushNotification.js +++ b/www/PushNotification.js @@ -110,6 +110,11 @@ PushNotification.prototype.setApplicationIconBadgeNumber = function(successCallb cordova.exec(successCallback, errorCallback, "PushPlugin", "setApplicationIconBadgeNumber", [{badge: badge}]); }; +// Call this to notifiy iOS native code that the push notification was processed +PushNotification.prototype.notificationProcessed = function() { + cordova.exec({}, {}, "PushPlugin", "notificationProcessed"); +}; + //------------------------------------------------------------------- if(!window.plugins) { From e4ec1a7eeb850ad2d8d687b04fedf115a55e45e0 Mon Sep 17 00:00:00 2001 From: Dimitar Date: Thu, 28 Jan 2016 16:49:47 +0200 Subject: [PATCH 02/12] receive notifications on cold start --- src/ios/AppDelegate+notification.m | 4 ++-- src/ios/PushPlugin.h | 4 +++- src/ios/PushPlugin.m | 8 +++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ios/AppDelegate+notification.m b/src/ios/AppDelegate+notification.m index 2c2a466e..0ec595c3 100644 --- a/src/ios/AppDelegate+notification.m +++ b/src/ios/AppDelegate+notification.m @@ -125,12 +125,12 @@ - (void)application:(UIApplication *) application handleActionWithIdentifier: (N completionHandler(); }); }; - NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:1]; + NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:2]; [params setObject:safeHandler forKey:@"handler"]; PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"]; pushHandler.notificationMessage = mutableNotification; pushHandler.params= params; - [pushHandler performSelectorOnMainThread:@selector(notificationReceived) withObject:pushHandler waitUntilDone:NO]; + [pushHandler notificationReceived]; } } #endif diff --git a/src/ios/PushPlugin.h b/src/ios/PushPlugin.h index 3a191652..7eb1b92e 100644 --- a/src/ios/PushPlugin.h +++ b/src/ios/PushPlugin.h @@ -30,9 +30,11 @@ @interface PushPlugin : CDVPlugin { NSDictionary *notificationMessage; + NSDictionary *params; BOOL isInline; NSString *notificationCallbackId; NSString *callback; + void (^_completionHandler)(); BOOL ready; } @@ -41,7 +43,7 @@ @property (nonatomic, copy) NSString *callback; @property (nonatomic, strong) NSDictionary *notificationMessage; -@property (nonatomic, strong) NSMutableDictionary *params; +@property (nonatomic, strong) NSDictionary *params; @property BOOL isInline; - (void)register:(CDVInvokedUrlCommand*)command; diff --git a/src/ios/PushPlugin.m b/src/ios/PushPlugin.m index 1451e196..b2cce828 100644 --- a/src/ios/PushPlugin.m +++ b/src/ios/PushPlugin.m @@ -426,14 +426,13 @@ - (void)notificationReceived { -(void) notificationProcessed:(CDVInvokedUrlCommand*)command { - NSLog(@"Push Plugin finish called"); + NSLog(@"Push Plugin notificationProcessed called"); [self.commandDelegate runInBackground:^ { UIApplication *app = [UIApplication sharedApplication]; - float finishTimer = (app.backgroundTimeRemaining > 20.0) ? 20.0 : app.backgroundTimeRemaining; dispatch_async(dispatch_get_main_queue(), ^{ - [NSTimer scheduledTimerWithTimeInterval:finishTimer + [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(stopBackgroundTask:) userInfo:nil @@ -449,9 +448,8 @@ -(void)stopBackgroundTask:(NSTimer*)timer NSLog(@"Push Plugin stopBackgroundTask called"); if (self.params) { - void (^_completionHandler)() = self.params[@"handler"]; + _completionHandler = [self.params[@"handler"] copy]; if (_completionHandler) { - NSLog(@"Push Plugin: stopBackgroundTask (remaining t: %f)", app.backgroundTimeRemaining); _completionHandler(); _completionHandler = nil; } From a35e1524ebf15603b4c6f4e8ba3e9f892dbca254 Mon Sep 17 00:00:00 2001 From: Dimitar Date: Fri, 29 Jan 2016 11:41:28 +0200 Subject: [PATCH 03/12] add handling of silent push notifications and textInput action --- plugin.xml | 6 +++++ src/ios/AppDelegate+notification.m | 35 +++++++++++++++++++++++++----- src/ios/PushPlugin.h | 3 ++- src/ios/PushPlugin.m | 29 +++++++++++++++++-------- www/PushNotification.js | 4 ++++ 5 files changed, 62 insertions(+), 15 deletions(-) diff --git a/plugin.xml b/plugin.xml index 86a158aa..f5306144 100755 --- a/plugin.xml +++ b/plugin.xml @@ -82,6 +82,12 @@ + + + remote-notification + + + diff --git a/src/ios/AppDelegate+notification.m b/src/ios/AppDelegate+notification.m index 0ec595c3..1850cf66 100644 --- a/src/ios/AppDelegate+notification.m +++ b/src/ios/AppDelegate+notification.m @@ -103,17 +103,42 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N } } +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void(^)(UIBackgroundFetchResult result))completionHandler +{ + NSLog(@"didReceiveRemoteNotification with fetchCompletionHandler"); + + void (^safeHandler)(UIBackgroundFetchResult) = ^(UIBackgroundFetchResult result){ + dispatch_async(dispatch_get_main_queue(), ^{ + completionHandler(result); + }); + }; + + NSMutableDictionary *mutableNotification = [userInfo mutableCopy]; + + NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:2]; + [params setObject:safeHandler forKey:@"silentNotificationHandler"]; + + PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"]; + pushHandler.notificationMessage = mutableNotification; + pushHandler.params= params; + [pushHandler notificationReceived]; +} + #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 // this method is invoked when: // - one of the buttons of an interactive notification is tapped // see https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html#//apple_ref/doc/uid/TP40008194-CH103-SW1 -- (void)application:(UIApplication *) application handleActionWithIdentifier: (NSString *) identifier forRemoteNotification: (NSDictionary *) notification completionHandler: (void (^)()) completionHandler { +- (void)application:(UIApplication *) application handleActionWithIdentifier: (NSString *) identifier forRemoteNotification: (NSDictionary *) notification withResponseInfo:(NSDictionary *)responseInfo completionHandler: (void (^)()) completionHandler { - // the notification already contains the category, but the client also needs the identifier (action button) NSMutableDictionary *mutableNotification = [notification mutableCopy]; - [mutableNotification setObject:identifier forKey:@"identifier"]; - NSLog(@"handleActionWithIdentifier"); + [mutableNotification setObject:identifier forKey:@"identifier"]; + + if(responseInfo != nil){ + NSString *textInput = [[NSString alloc]initWithFormat:@"%@",[responseInfo objectForKey:@"UIUserNotificationActionResponseTypedTextKey"]]; + [mutableNotification setValue:textInput forKey:@"textInput"]; + } + NSLog(@"handleActionWithIdentifier"); if (application.applicationState == UIApplicationStateActive) { PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"]; pushHandler.notificationMessage = mutableNotification; @@ -126,7 +151,7 @@ - (void)application:(UIApplication *) application handleActionWithIdentifier: (N }); }; NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:2]; - [params setObject:safeHandler forKey:@"handler"]; + [params setObject:safeHandler forKey:@"remoteNotificationHandler"]; PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"]; pushHandler.notificationMessage = mutableNotification; pushHandler.params= params; diff --git a/src/ios/PushPlugin.h b/src/ios/PushPlugin.h index 7eb1b92e..cf20c96a 100644 --- a/src/ios/PushPlugin.h +++ b/src/ios/PushPlugin.h @@ -34,7 +34,8 @@ BOOL isInline; NSString *notificationCallbackId; NSString *callback; - void (^_completionHandler)(); + void (^remoteNotificationHandler)(); + void (^silentNotificationHandler)(UIBackgroundFetchResult); BOOL ready; } diff --git a/src/ios/PushPlugin.m b/src/ios/PushPlugin.m index b2cce828..5431c1e6 100644 --- a/src/ios/PushPlugin.m +++ b/src/ios/PushPlugin.m @@ -175,6 +175,13 @@ - (BOOL)createNotificationAction:(NSDictionary *)category // Set whether the action requires the user to authenticate BOOL isAuthRequired = [[action objectForKey:@"authenticationRequired"] isEqual:[NSNumber numberWithBool:YES]]; nsAction.authenticationRequired = isAuthRequired; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 + // Check if the action is actually a text input + BOOL isTextInput = [@"textInput" isEqualToString:[action objectForKey:@"behavior"]]; + if(isTextInput){ + nsAction.behavior = UIUserNotificationActionBehaviorTextInput; + } +#endif [nsActions addObject:nsAction]; } return YES; @@ -414,9 +421,7 @@ - (void)notificationReceived { [jsonStr appendFormat:@"foreground:\"%d\"", 0]; [jsonStr appendString:@"}"]; - - NSLog(@"Msg: %@", jsonStr); - + NSString * jsCallBack = [NSString stringWithFormat:@"%@(%@);", self.callback, jsonStr]; [self.webView performSelectorOnMainThread:@selector(stringByEvaluatingJavaScriptFromString:) withObject:jsCallBack waitUntilDone:NO]; @@ -445,13 +450,19 @@ -(void)stopBackgroundTask:(NSTimer*)timer { UIApplication *app = [UIApplication sharedApplication]; - NSLog(@"Push Plugin stopBackgroundTask called"); - if (self.params) { - _completionHandler = [self.params[@"handler"] copy]; - if (_completionHandler) { - _completionHandler(); - _completionHandler = nil; + remoteNotificationHandler = [self.params[@"remoteNotificationHandler"] copy]; + if (remoteNotificationHandler) { + remoteNotificationHandler(); + NSLog(@"remoteNotificationHandler called"); + remoteNotificationHandler = nil; + } + + silentNotificationHandler = [self.params[@"silentNotificationHandler"] copy]; + if (silentNotificationHandler) { + silentNotificationHandler(UIBackgroundFetchResultNewData); + NSLog(@"silentNotificationHandler called"); + silentNotificationHandler = nil; } } } diff --git a/www/PushNotification.js b/www/PushNotification.js index 3f0babf9..a3c0a315 100644 --- a/www/PushNotification.js +++ b/www/PushNotification.js @@ -30,6 +30,10 @@ PushNotification.prototype.UserNotificationActivationMode = { Background : "background" }; +PushNotification.prototype.ActionBehavior = { + TextInput : "textInput" +}; + PushNotification.prototype.registerUserNotificationSettings = function(successCallback, errorCallback, options) { if (errorCallback == null) { errorCallback = function() {}} From b47e1a129c346f9759144fa0e4a1b510ec44fc17 Mon Sep 17 00:00:00 2001 From: Dimitar Date: Tue, 2 Feb 2016 15:06:04 +0200 Subject: [PATCH 04/12] do not enable ios remote-notifications by default --- plugin.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plugin.xml b/plugin.xml index f5306144..86a158aa 100755 --- a/plugin.xml +++ b/plugin.xml @@ -82,12 +82,6 @@ - - - remote-notification - - - From ba20be70a611e4c67a81c3e05159aa893d59454c Mon Sep 17 00:00:00 2001 From: Dimitar Date: Tue, 2 Feb 2016 16:54:55 +0200 Subject: [PATCH 05/12] add information about new features --- README.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index eb381310..86f152ff 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ For further information you can take a look into the Backend Services hybrid pus pushNotification.unregister(successHandler, errorHandler, options); -- iOS 8 interactive push notifications support (available from v.2.5 and above) +- iOS 8 interactive push notifications support (available from v2.5 and above) // Get the push plugin instance var pushPlugin = window.plugins.pushNotification; @@ -98,6 +98,32 @@ For further information you can take a look into the Backend Services hybrid pus ); +- iOS 9 text input support (available from v3.1 and above) + + // Define a Text Input Action + var replyAction = { + identifier: 'REPLY_IDENTIFIER', + title: 'Reply', + activationMode: pushPlugin.UserNotificationActivationMode.Background, + destructive: false, + authenticationRequired: true, + behavior: window.plugins.pushNotification.ActionBehavior.TextInput + }; + +- iOS silent/content-available push notifications (available from v3.1 and above) - in order to use that kind of push notifiations, add the following snippet to the section in the plugin.xml file: + + + + remote-notification + + + +- **IMPORTANT**: When using interactive iOS push notifications with background activation mode or iOS silent push notifications, you **must** call the following function, once you are done processing the push notification object: + + pushPlugin.notificationProcessed() + This way you'll be able to execute your javascript callback and then notify the operating system to put back your app in background, which is the correct approach to handle such notifications by iOS. + + - Set an application icon badge number (iOS only) // sets the application badge to the provided value From 4028f62db73350d59d7b0abb4997f93e5e755747 Mon Sep 17 00:00:00 2001 From: Dimitar Date: Tue, 2 Feb 2016 16:55:25 +0200 Subject: [PATCH 06/12] bump version --- plugin.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin.xml b/plugin.xml index 86a158aa..11c90cc9 100755 --- a/plugin.xml +++ b/plugin.xml @@ -2,7 +2,7 @@ + version="3.1.0"> PushPlugin @@ -80,7 +80,7 @@ - + From f50b73df1ab3d9c2108f78a9f3e72d796066bf33 Mon Sep 17 00:00:00 2001 From: Dimitar Date: Mon, 8 Feb 2016 11:46:02 +0200 Subject: [PATCH 07/12] add backward compatibility for ios8 --- src/ios/AppDelegate+notification.m | 31 +++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/ios/AppDelegate+notification.m b/src/ios/AppDelegate+notification.m index 1850cf66..df63ac08 100644 --- a/src/ios/AppDelegate+notification.m +++ b/src/ios/AppDelegate+notification.m @@ -124,7 +124,7 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N [pushHandler notificationReceived]; } -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 // this method is invoked when: // - one of the buttons of an interactive notification is tapped // see https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html#//apple_ref/doc/uid/TP40008194-CH103-SW1 @@ -158,6 +158,35 @@ - (void)application:(UIApplication *) application handleActionWithIdentifier: (N [pushHandler notificationReceived]; } } +#elif __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 +// this method is invoked when: +// - one of the buttons of an interactive notification is tapped +// see https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html#//apple_ref/doc/uid/TP40008194-CH103-SW1 +- (void)application:(UIApplication *) application handleActionWithIdentifier: (NSString *) identifier forRemoteNotification: (NSDictionary *) notification completionHandler: (void (^)()) completionHandler { + + NSMutableDictionary *mutableNotification = [notification mutableCopy]; + [mutableNotification setObject:identifier forKey:@"identifier"]; + + NSLog(@"handleActionWithIdentifier"); + if (application.applicationState == UIApplicationStateActive) { + PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"]; + pushHandler.notificationMessage = mutableNotification; + pushHandler.isInline = YES; + [pushHandler notificationReceived]; + } else { + void (^safeHandler)() = ^(void){ + dispatch_async(dispatch_get_main_queue(), ^{ + completionHandler(); + }); + }; + NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:2]; + [params setObject:safeHandler forKey:@"remoteNotificationHandler"]; + PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"]; + pushHandler.notificationMessage = mutableNotification; + pushHandler.params= params; + [pushHandler notificationReceived]; + } +} #endif From a9dc1da4613fc6f9adfd68cea2e34fe7046454d6 Mon Sep 17 00:00:00 2001 From: Dimitar Date: Mon, 8 Feb 2016 18:45:21 +0200 Subject: [PATCH 08/12] add check for textinput and ios8 --- src/ios/PushPlugin.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ios/PushPlugin.m b/src/ios/PushPlugin.m index 5431c1e6..5f180f25 100644 --- a/src/ios/PushPlugin.m +++ b/src/ios/PushPlugin.m @@ -175,13 +175,13 @@ - (BOOL)createNotificationAction:(NSDictionary *)category // Set whether the action requires the user to authenticate BOOL isAuthRequired = [[action objectForKey:@"authenticationRequired"] isEqual:[NSNumber numberWithBool:YES]]; nsAction.authenticationRequired = isAuthRequired; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 - // Check if the action is actually a text input + + // Check if the action is actually a text input and behavior is supported BOOL isTextInput = [@"textInput" isEqualToString:[action objectForKey:@"behavior"]]; - if(isTextInput){ + if(isTextInput && [nsAction respondsToSelector:NSSelectorFromString(@"setBehvaior")]){ nsAction.behavior = UIUserNotificationActionBehaviorTextInput; } -#endif + [nsActions addObject:nsAction]; } return YES; From cb6ede41969029ee8821fade78707069bd130c97 Mon Sep 17 00:00:00 2001 From: Dimitar Date: Tue, 9 Feb 2016 13:48:41 +0200 Subject: [PATCH 09/12] fix signature for selector --- src/ios/PushPlugin.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ios/PushPlugin.m b/src/ios/PushPlugin.m index 5f180f25..68fbda11 100644 --- a/src/ios/PushPlugin.m +++ b/src/ios/PushPlugin.m @@ -178,7 +178,7 @@ - (BOOL)createNotificationAction:(NSDictionary *)category // Check if the action is actually a text input and behavior is supported BOOL isTextInput = [@"textInput" isEqualToString:[action objectForKey:@"behavior"]]; - if(isTextInput && [nsAction respondsToSelector:NSSelectorFromString(@"setBehvaior")]){ + if(isTextInput && [nsAction respondsToSelector:NSSelectorFromString(@"setBehavior:")]){ nsAction.behavior = UIUserNotificationActionBehaviorTextInput; } From 05b0b9ac50d31074eb1a9a139730d4604f5d431e Mon Sep 17 00:00:00 2001 From: Dimitar Date: Mon, 15 Feb 2016 12:18:48 +0200 Subject: [PATCH 10/12] disable handling of silent push notifications --- src/ios/AppDelegate+notification.m | 56 +++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/src/ios/AppDelegate+notification.m b/src/ios/AppDelegate+notification.m index df63ac08..c22d05f1 100644 --- a/src/ios/AppDelegate+notification.m +++ b/src/ios/AppDelegate+notification.m @@ -103,26 +103,48 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N } } -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void(^)(UIBackgroundFetchResult result))completionHandler +/*- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void(^)(UIBackgroundFetchResult result))completionHandler { NSLog(@"didReceiveRemoteNotification with fetchCompletionHandler"); - void (^safeHandler)(UIBackgroundFetchResult) = ^(UIBackgroundFetchResult result){ - dispatch_async(dispatch_get_main_queue(), ^{ - completionHandler(result); - }); - }; - - NSMutableDictionary *mutableNotification = [userInfo mutableCopy]; - - NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:2]; - [params setObject:safeHandler forKey:@"silentNotificationHandler"]; - - PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"]; - pushHandler.notificationMessage = mutableNotification; - pushHandler.params= params; - [pushHandler notificationReceived]; -} + if (application.applicationState == UIApplicationStateActive) { + PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"]; + pushHandler.notificationMessage = userInfo; + pushHandler.isInline = YES; + [pushHandler notificationReceived]; + completionHandler(UIBackgroundFetchResultNewData); + } + else { + long silent = 0; + id aps = [userInfo objectForKey:@"aps"]; + id contentAvailable = [aps objectForKey:@"content-available"]; + if ([contentAvailable isKindOfClass:[NSString class]] && [contentAvailable isEqualToString:@"1"]) { + silent = 1; + } else if ([contentAvailable isKindOfClass:[NSNumber class]]) { + silent = [contentAvailable integerValue]; + } + + if (silent == 1) { + void (^safeHandler)(UIBackgroundFetchResult) = ^(UIBackgroundFetchResult result){ + dispatch_async(dispatch_get_main_queue(), ^{ + completionHandler(result); + }); + }; + + NSMutableDictionary *mutableNotification = [userInfo mutableCopy]; + NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:2]; + [params setObject:safeHandler forKey:@"silentNotificationHandler"]; + PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"]; + pushHandler.notificationMessage = mutableNotification; + pushHandler.params= params; + [pushHandler notificationReceived]; + } else { + self.launchNotification = userInfo; + completionHandler(UIBackgroundFetchResultNewData); + } + } + +}*/ #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 // this method is invoked when: From c92148ad9520deae254ed1777e614a8401f5e77f Mon Sep 17 00:00:00 2001 From: Dimitar Dimitrov Date: Mon, 15 Feb 2016 15:44:20 +0200 Subject: [PATCH 11/12] remove unnecessary information --- README.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/README.md b/README.md index 86f152ff..35945d1d 100644 --- a/README.md +++ b/README.md @@ -110,15 +110,7 @@ For further information you can take a look into the Backend Services hybrid pus behavior: window.plugins.pushNotification.ActionBehavior.TextInput }; -- iOS silent/content-available push notifications (available from v3.1 and above) - in order to use that kind of push notifiations, add the following snippet to the section in the plugin.xml file: - - - - remote-notification - - - -- **IMPORTANT**: When using interactive iOS push notifications with background activation mode or iOS silent push notifications, you **must** call the following function, once you are done processing the push notification object: +- **IMPORTANT**: When using interactive iOS push notifications with background activation mode, you **must** call the following function, once you are done processing the push notification object: pushPlugin.notificationProcessed() This way you'll be able to execute your javascript callback and then notify the operating system to put back your app in background, which is the correct approach to handle such notifications by iOS. From 5798193cc4b01962dec72ed9448aaf7a533e4746 Mon Sep 17 00:00:00 2001 From: Dimitar Dimitrov Date: Mon, 15 Feb 2016 15:46:14 +0200 Subject: [PATCH 12/12] fix action definition --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 35945d1d..587ac21c 100644 --- a/README.md +++ b/README.md @@ -104,10 +104,10 @@ For further information you can take a look into the Backend Services hybrid pus var replyAction = { identifier: 'REPLY_IDENTIFIER', title: 'Reply', - activationMode: pushPlugin.UserNotificationActivationMode.Background, + activationMode: window.plugins.pushNotification.UserNotificationActivationMode.Background, destructive: false, authenticationRequired: true, - behavior: window.plugins.pushNotification.ActionBehavior.TextInput + behavior: window.plugins.pushNotification.ActionBehavior.TextInput }; - **IMPORTANT**: When using interactive iOS push notifications with background activation mode, you **must** call the following function, once you are done processing the push notification object: