diff options
| author | Jules Laplace <jules@okfoc.us> | 2015-11-30 18:21:01 -0500 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2015-11-30 18:21:01 -0500 |
| commit | ded2f8928dd509acc8d4ae1e4131b622c7bb4d9c (patch) | |
| tree | a576defc78fac3b9c2c0d8a7beb18e78d6466255 /StoneIsland/platforms | |
| parent | 60bd9bf61e4d1f3fb3925807ca754f89743cfade (diff) | |
phonegap-plugin-push
Diffstat (limited to 'StoneIsland/platforms')
9 files changed, 856 insertions, 1 deletions
diff --git a/StoneIsland/platforms/ios/StoneIsland.xcodeproj/project.pbxproj b/StoneIsland/platforms/ios/StoneIsland.xcodeproj/project.pbxproj index b1a129c4..e75b8393 100644 --- a/StoneIsland/platforms/ios/StoneIsland.xcodeproj/project.pbxproj +++ b/StoneIsland/platforms/ios/StoneIsland.xcodeproj/project.pbxproj @@ -53,6 +53,8 @@ 28FA0D2F417F4E6891D4A2A3 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E63CFDA045E649E8A2E41A6E /* SystemConfiguration.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 032ABF0840BB48E0B3DD2F92 /* CDVSplashScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 73C53A36FBD446C9BB33C265 /* CDVSplashScreen.m */; }; C2BF0352F9A246A886C16676 /* CDVViewController+SplashScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B5B2F329484022BEE14D58 /* CDVViewController+SplashScreen.m */; }; + 4A80D26AF40046D7AD4979A9 /* AppDelegate+notification.m in Sources */ = {isa = PBXBuildFile; fileRef = EE6BC93769C04564BA35B9B4 /* AppDelegate+notification.m */; }; + 4ABEABC16E324DEEB7A72E3B /* PushPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 450F6AEB11F34A6080834666 /* PushPlugin.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -142,6 +144,10 @@ 58B5B2F329484022BEE14D58 /* CDVViewController+SplashScreen.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "CDVViewController+SplashScreen.m"; path = "cordova-plugin-splashscreen/CDVViewController+SplashScreen.m"; sourceTree = "<group>"; fileEncoding = 4; }; 3E6B9A9492B847CD8FE87334 /* CDVSplashScreen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "CDVSplashScreen.h"; path = "cordova-plugin-splashscreen/CDVSplashScreen.h"; sourceTree = "<group>"; fileEncoding = 4; }; AEFF8C2B3066438BB4111A39 /* CDVViewController+SplashScreen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "CDVViewController+SplashScreen.h"; path = "cordova-plugin-splashscreen/CDVViewController+SplashScreen.h"; sourceTree = "<group>"; fileEncoding = 4; }; + EE6BC93769C04564BA35B9B4 /* AppDelegate+notification.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "AppDelegate+notification.m"; path = "phonegap-plugin-push/AppDelegate+notification.m"; sourceTree = "<group>"; fileEncoding = 4; }; + 450F6AEB11F34A6080834666 /* PushPlugin.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "PushPlugin.m"; path = "phonegap-plugin-push/PushPlugin.m"; sourceTree = "<group>"; fileEncoding = 4; }; + 9F746E936D46499681DECD6E /* AppDelegate+notification.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "AppDelegate+notification.h"; path = "phonegap-plugin-push/AppDelegate+notification.h"; sourceTree = "<group>"; fileEncoding = 4; }; + A3C287A7B1C74C02A8585FC2 /* PushPlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "PushPlugin.h"; path = "phonegap-plugin-push/PushPlugin.h"; sourceTree = "<group>"; fileEncoding = 4; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -267,6 +273,10 @@ 58B5B2F329484022BEE14D58 /* CDVViewController+SplashScreen.m */, 3E6B9A9492B847CD8FE87334 /* CDVSplashScreen.h */, AEFF8C2B3066438BB4111A39 /* CDVViewController+SplashScreen.h */, + EE6BC93769C04564BA35B9B4 /* AppDelegate+notification.m */, + 450F6AEB11F34A6080834666 /* PushPlugin.m */, + 9F746E936D46499681DECD6E /* AppDelegate+notification.h */, + A3C287A7B1C74C02A8585FC2 /* PushPlugin.h */, ); name = Plugins; path = "StoneIsland/Plugins"; @@ -462,6 +472,8 @@ 79E64CBE70114745BC7D1E61 /* CDVReachability.m in Sources */, 032ABF0840BB48E0B3DD2F92 /* CDVSplashScreen.m in Sources */, C2BF0352F9A246A886C16676 /* CDVViewController+SplashScreen.m in Sources */, + 4A80D26AF40046D7AD4979A9 /* AppDelegate+notification.m in Sources */, + 4ABEABC16E324DEEB7A72E3B /* PushPlugin.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/StoneIsland/platforms/ios/StoneIsland/Plugins/phonegap-plugin-push/AppDelegate+notification.h b/StoneIsland/platforms/ios/StoneIsland/Plugins/phonegap-plugin-push/AppDelegate+notification.h new file mode 100644 index 00000000..be79903e --- /dev/null +++ b/StoneIsland/platforms/ios/StoneIsland/Plugins/phonegap-plugin-push/AppDelegate+notification.h @@ -0,0 +1,21 @@ +// +// AppDelegate+notification.h +// pushtest +// +// Created by Robert Easterday on 10/26/12. +// +// + +#import "AppDelegate.h" + +@interface AppDelegate (notification) +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo; +- (void)applicationDidBecomeActive:(UIApplication *)application; +- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler; +- (id) getCommandInstance:(NSString*)className; + +@property (nonatomic, retain) NSDictionary *launchNotification; + +@end diff --git a/StoneIsland/platforms/ios/StoneIsland/Plugins/phonegap-plugin-push/AppDelegate+notification.m b/StoneIsland/platforms/ios/StoneIsland/Plugins/phonegap-plugin-push/AppDelegate+notification.m new file mode 100644 index 00000000..8b4ed161 --- /dev/null +++ b/StoneIsland/platforms/ios/StoneIsland/Plugins/phonegap-plugin-push/AppDelegate+notification.m @@ -0,0 +1,167 @@ +// +// AppDelegate+notification.m +// pushtest +// +// Created by Robert Easterday on 10/26/12. +// +// + +#import "AppDelegate+notification.h" +#import "PushPlugin.h" +#import <objc/runtime.h> + +static char launchNotificationKey; + +@implementation AppDelegate (notification) + +- (id) getCommandInstance:(NSString*)className +{ + return [self.viewController getCommandInstance:className]; +} + +// its dangerous to override a method from within a category. +// Instead we will use method swizzling. we set this up in the load call. ++ (void)load +{ + Method original, swizzled; + + original = class_getInstanceMethod(self, @selector(init)); + swizzled = class_getInstanceMethod(self, @selector(swizzled_init)); + method_exchangeImplementations(original, swizzled); +} + +- (AppDelegate *)swizzled_init +{ + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(createNotificationChecker:) + name:@"UIApplicationDidFinishLaunchingNotification" object:nil]; + + // This actually calls the original init method over in AppDelegate. Equivilent to calling super + // on an overrided method, this is not recursive, although it appears that way. neat huh? + return [self swizzled_init]; +} + +// This code will be called immediately after application:didFinishLaunchingWithOptions:. We need +// to process notifications in cold-start situations +- (void)createNotificationChecker:(NSNotification *)notification +{ + if (notification) + { + NSDictionary *launchOptions = [notification userInfo]; + if (launchOptions) + self.launchNotification = [launchOptions objectForKey: @"UIApplicationLaunchOptionsRemoteNotificationKey"]; + } +} + +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; + [pushHandler didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; +} + +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; + [pushHandler didFailToRegisterForRemoteNotificationsWithError:error]; +} + +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + NSLog(@"didReceiveNotification with fetchCompletionHandler"); + + // app is in the foreground so call notification callback + if (application.applicationState == UIApplicationStateActive) { + NSLog(@"app active"); + PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; + pushHandler.notificationMessage = userInfo; + pushHandler.isInline = YES; + [pushHandler notificationReceived]; + + completionHandler(UIBackgroundFetchResultNewData); + } + // app is in background or in stand by + else { + NSLog(@"app in-active"); + + // do some convoluted logic to find out if this should be a silent push. + 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) { + NSLog(@"this should be a silent push"); + void (^safeHandler)(UIBackgroundFetchResult) = ^(UIBackgroundFetchResult result){ + dispatch_async(dispatch_get_main_queue(), ^{ + completionHandler(result); + }); + }; + + NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:2]; + [params setObject:safeHandler forKey:@"handler"]; + + PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; + pushHandler.notificationMessage = userInfo; + pushHandler.isInline = NO; + pushHandler.handlerObj = params; + [pushHandler notificationReceived]; + } else { + NSLog(@"just put it in the shade"); + //save it for later + self.launchNotification = userInfo; + + completionHandler(UIBackgroundFetchResultNewData); + } + } +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + + NSLog(@"active"); + + PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; + if (pushHandler.clearBadge) { + NSLog(@"PushPlugin clearing badge"); + //zero badge + application.applicationIconBadgeNumber = 0; + } else { + NSLog(@"PushPlugin skip clear badge"); + } + + if (self.launchNotification) { + pushHandler.isInline = NO; + pushHandler.notificationMessage = self.launchNotification; + self.launchNotification = nil; + [pushHandler performSelectorOnMainThread:@selector(notificationReceived) withObject:pushHandler waitUntilDone:NO]; + } +} + +//For interactive notification only +- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler +{ + //handle the actions + if ([identifier isEqualToString:@"declineAction"]){ + } + else if ([identifier isEqualToString:@"answerAction"]){ + } +} + + +// The accessors use an Associative Reference since you can't define a iVar in a category +// http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocAssociativeReferences.html +- (NSMutableArray *)launchNotification +{ + return objc_getAssociatedObject(self, &launchNotificationKey); +} + +- (void)setLaunchNotification:(NSDictionary *)aDictionary +{ + objc_setAssociatedObject(self, &launchNotificationKey, aDictionary, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)dealloc +{ + self.launchNotification = nil; // clear the association and release the object +} + +@end diff --git a/StoneIsland/platforms/ios/StoneIsland/Plugins/phonegap-plugin-push/PushPlugin.h b/StoneIsland/platforms/ios/StoneIsland/Plugins/phonegap-plugin-push/PushPlugin.h new file mode 100644 index 00000000..5b88398e --- /dev/null +++ b/StoneIsland/platforms/ios/StoneIsland/Plugins/phonegap-plugin-push/PushPlugin.h @@ -0,0 +1,62 @@ +/* + Copyright 2009-2011 Urban Airship Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binaryform must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided withthe distribution. + + THIS SOFTWARE IS PROVIDED BY THE URBAN AIRSHIP INC``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL URBAN AIRSHIP INC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <Foundation/Foundation.h> +#import <Cordova/CDV.h> +#import <Cordova/CDVPlugin.h> + +@interface PushPlugin : CDVPlugin +{ + NSDictionary *notificationMessage; + BOOL isInline; + NSString *notificationCallbackId; + NSString *callback; + BOOL clearBadge; + + NSDictionary *handlerObj; + void (^completionHandler)(UIBackgroundFetchResult); + + BOOL ready; +} + +@property (nonatomic, copy) NSString *callbackId; +@property (nonatomic, copy) NSString *notificationCallbackId; +@property (nonatomic, copy) NSString *callback; + +@property (nonatomic, strong) NSDictionary *notificationMessage; +@property BOOL isInline; +@property BOOL clearBadge; +@property (nonatomic, strong) NSDictionary *handlerObj; + +- (void)init:(CDVInvokedUrlCommand*)command; +- (void)unregister:(CDVInvokedUrlCommand*)command; + +- (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; +- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; + +- (void)setNotificationMessage:(NSDictionary *)notification; +- (void)notificationReceived; + +@end diff --git a/StoneIsland/platforms/ios/StoneIsland/Plugins/phonegap-plugin-push/PushPlugin.m b/StoneIsland/platforms/ios/StoneIsland/Plugins/phonegap-plugin-push/PushPlugin.m new file mode 100644 index 00000000..40f494d1 --- /dev/null +++ b/StoneIsland/platforms/ios/StoneIsland/Plugins/phonegap-plugin-push/PushPlugin.m @@ -0,0 +1,347 @@ +/* + Copyright 2009-2011 Urban Airship Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binaryform must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided withthe distribution. + + THIS SOFTWARE IS PROVIDED BY THE URBAN AIRSHIP INC``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL URBAN AIRSHIP INC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "PushPlugin.h" + +@implementation PushPlugin + +@synthesize notificationMessage; +@synthesize isInline; + +@synthesize callbackId; +@synthesize notificationCallbackId; +@synthesize callback; +@synthesize clearBadge; +@synthesize handlerObj; + +- (void)unregister:(CDVInvokedUrlCommand*)command; +{ + self.callbackId = command.callbackId; + + [[UIApplication sharedApplication] unregisterForRemoteNotifications]; + [self successWithMessage:@"unregistered"]; +} + +- (void)init:(CDVInvokedUrlCommand*)command; +{ + [self.commandDelegate runInBackground:^ { + + NSLog(@"Push Plugin register called"); + self.callbackId = command.callbackId; + + NSMutableDictionary* options = [command.arguments objectAtIndex:0]; + NSMutableDictionary* iosOptions = [options objectForKey:@"ios"]; + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + UIUserNotificationType UserNotificationTypes = UIUserNotificationTypeNone; +#endif + UIRemoteNotificationType notificationTypes = UIRemoteNotificationTypeNone; + + id badgeArg = [iosOptions objectForKey:@"badge"]; + id soundArg = [iosOptions objectForKey:@"sound"]; + id alertArg = [iosOptions objectForKey:@"alert"]; + id clearBadgeArg = [iosOptions objectForKey:@"clearBadge"]; + + if (([badgeArg isKindOfClass:[NSString class]] && [badgeArg isEqualToString:@"true"]) || [badgeArg boolValue]) + { + notificationTypes |= UIRemoteNotificationTypeBadge; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + UserNotificationTypes |= UIUserNotificationTypeBadge; +#endif + } + + if (([soundArg isKindOfClass:[NSString class]] && [soundArg isEqualToString:@"true"]) || [soundArg boolValue]) + { + notificationTypes |= UIRemoteNotificationTypeSound; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + UserNotificationTypes |= UIUserNotificationTypeSound; +#endif + } + + if (([alertArg isKindOfClass:[NSString class]] && [alertArg isEqualToString:@"true"]) || [alertArg boolValue]) + { + notificationTypes |= UIRemoteNotificationTypeAlert; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + UserNotificationTypes |= UIUserNotificationTypeAlert; +#endif + } + + notificationTypes |= UIRemoteNotificationTypeNewsstandContentAvailability; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + UserNotificationTypes |= UIUserNotificationActivationModeBackground; +#endif + + if (clearBadgeArg == nil || ([clearBadgeArg isKindOfClass:[NSString class]] && [clearBadgeArg isEqualToString:@"false"]) || ![clearBadgeArg boolValue]) { + NSLog(@"PushPlugin.register: setting badge to false"); + clearBadge = NO; + } else { + NSLog(@"PushPlugin.register: setting badge to true"); + clearBadge = YES; + [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; + } + NSLog(@"PushPlugin.register: clear badge is set to %d", clearBadge); + + if (notificationTypes == UIRemoteNotificationTypeNone) + NSLog(@"PushPlugin.register: Push notification type is set to none"); + + isInline = NO; + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + if ([[UIApplication sharedApplication]respondsToSelector:@selector(registerUserNotificationSettings:)]) { + UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UserNotificationTypes categories:nil]; + [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; + [[UIApplication sharedApplication] registerForRemoteNotifications]; + } else { + [[UIApplication sharedApplication] registerForRemoteNotificationTypes: + (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; + } +#else + [[UIApplication sharedApplication] registerForRemoteNotificationTypes: + (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; +#endif + + if (notificationMessage) // if there is a pending startup notification + [self notificationReceived]; // go ahead and process it + + }]; +} + +- (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + if (self.callbackId == nil) { + NSLog(@"Unexpected call to didRegisterForRemoteNotificationsWithDeviceToken, ignoring: %@", deviceToken); + return; + } + NSLog(@"Push Plugin register success: %@", deviceToken); + + NSMutableDictionary *results = [NSMutableDictionary dictionary]; + NSString *token = [[[[deviceToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""] + stringByReplacingOccurrencesOfString:@">" withString:@""] + stringByReplacingOccurrencesOfString: @" " withString: @""]; + [results setValue:token forKey:@"deviceToken"]; + +#if !TARGET_IPHONE_SIMULATOR + // Get Bundle Info for Remote Registration (handy if you have more than one app) + [results setValue:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"] forKey:@"appName"]; + [results setValue:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] forKey:@"appVersion"]; + + // Check what Notifications the user has turned on. We registered for all three, but they may have manually disabled some or all of them. +#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) + + NSUInteger rntypes; + if (!SYSTEM_VERSION_LESS_THAN(@"8.0")) { + rntypes = [[[UIApplication sharedApplication] currentUserNotificationSettings] types]; + } else { + rntypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes]; + } + + // Set the defaults to disabled unless we find otherwise... + NSString *pushBadge = @"disabled"; + NSString *pushAlert = @"disabled"; + NSString *pushSound = @"disabled"; + + // Check what Registered Types are turned on. This is a bit tricky since if two are enabled, and one is off, it will return a number 2... not telling you which + // one is actually disabled. So we are literally checking to see if rnTypes matches what is turned on, instead of by number. The "tricky" part is that the + // single notification types will only match if they are the ONLY one enabled. Likewise, when we are checking for a pair of notifications, it will only be + // true if those two notifications are on. This is why the code is written this way + if(rntypes & UIRemoteNotificationTypeBadge){ + pushBadge = @"enabled"; + } + if(rntypes & UIRemoteNotificationTypeAlert) { + pushAlert = @"enabled"; + } + if(rntypes & UIRemoteNotificationTypeSound) { + pushSound = @"enabled"; + } + + [results setValue:pushBadge forKey:@"pushBadge"]; + [results setValue:pushAlert forKey:@"pushAlert"]; + [results setValue:pushSound forKey:@"pushSound"]; + + // Get the users Device Model, Display Name, Token & Version Number + UIDevice *dev = [UIDevice currentDevice]; + [results setValue:dev.name forKey:@"deviceName"]; + [results setValue:dev.model forKey:@"deviceModel"]; + [results setValue:dev.systemVersion forKey:@"deviceSystemVersion"]; + + // Send result to trigger 'registration' event but keep callback + NSMutableDictionary* message = [NSMutableDictionary dictionaryWithCapacity:1]; + [message setObject:token forKey:@"registrationId"]; + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:message]; + [pluginResult setKeepCallbackAsBool:YES]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; +#endif +} + +- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error +{ + if (self.callbackId == nil) { + NSLog(@"Unexpected call to didFailToRegisterForRemoteNotificationsWithError, ignoring: %@", error); + return; + } + NSLog(@"Push Plugin register failed"); + [self failWithMessage:@"" withError:error]; +} + +- (void)notificationReceived { + NSLog(@"Notification received"); + + if (notificationMessage && self.callbackId != nil) + { + NSMutableDictionary* message = [NSMutableDictionary dictionaryWithCapacity:4]; + NSMutableDictionary* additionalData = [NSMutableDictionary dictionaryWithCapacity:4]; + + + for (id key in notificationMessage) { + if ([key isEqualToString:@"aps"]) { + id aps = [notificationMessage objectForKey:@"aps"]; + + for(id key in aps) { + NSLog(@"Push Plugin key: %@", key); + id value = [aps objectForKey:key]; + + if ([key isEqualToString:@"alert"]) { + if ([value isKindOfClass:[NSDictionary class]]) { + for (id messageKey in value) { + id messageValue = [value objectForKey:messageKey]; + if ([messageKey isEqualToString:@"body"]) { + [message setObject:messageValue forKey:@"message"]; + } else if ([messageKey isEqualToString:@"title"]) { + [message setObject:messageValue forKey:@"title"]; + } else { + [additionalData setObject:messageValue forKey:messageKey]; + } + } + } + else { + [message setObject:value forKey:@"message"]; + } + } else if ([key isEqualToString:@"title"]) { + [message setObject:value forKey:@"title"]; + } else if ([key isEqualToString:@"badge"]) { + [message setObject:value forKey:@"count"]; + } else if ([key isEqualToString:@"sound"]) { + [message setObject:value forKey:@"sound"]; + } else if ([key isEqualToString:@"image"]) { + [message setObject:value forKey:@"image"]; + } else { + [additionalData setObject:value forKey:key]; + } + } + } else { + [additionalData setObject:[notificationMessage objectForKey:key] forKey:key]; + } + } + + if (isInline) { + [additionalData setObject:[NSNumber numberWithBool:YES] forKey:@"foreground"]; + } else { + [additionalData setObject:[NSNumber numberWithBool:NO] forKey:@"foreground"]; + } + + [message setObject:additionalData forKey:@"additionalData"]; + + // send notification message + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:message]; + [pluginResult setKeepCallbackAsBool:YES]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; + + self.notificationMessage = nil; + } +} + +- (void)setApplicationIconBadgeNumber:(CDVInvokedUrlCommand *)command +{ + NSMutableDictionary* options = [command.arguments objectAtIndex:0]; + int badge = [[options objectForKey:@"badge"] intValue] ?: 0; + + [[UIApplication sharedApplication] setApplicationIconBadgeNumber:badge]; + + NSString* message = [NSString stringWithFormat:@"app badge count set to %d", badge]; + CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message]; + [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; +} + +- (void)getApplicationIconBadgeNumber:(CDVInvokedUrlCommand *)command +{ + NSInteger badge = [UIApplication sharedApplication].applicationIconBadgeNumber; + + CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(int)badge]; + [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; +} + +-(void)successWithMessage:(NSString *)message +{ + if (self.callbackId != nil) + { + CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message]; + [self.commandDelegate sendPluginResult:commandResult callbackId:self.callbackId]; + } +} + +-(void)failWithMessage:(NSString *)message withError:(NSError *)error +{ + NSString *errorMessage = (error) ? [NSString stringWithFormat:@"%@ - %@", message, [error localizedDescription]] : message; + CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errorMessage]; + + [self.commandDelegate sendPluginResult:commandResult callbackId:self.callbackId]; +} + +-(void) finish:(CDVInvokedUrlCommand*)command +{ + NSLog(@"Push Plugin finish called"); + + [self.commandDelegate runInBackground:^ { + UIApplication *app = [UIApplication sharedApplication]; + float finishTimer = (app.backgroundTimeRemaining > 20.0) ? 20.0 : app.backgroundTimeRemaining; + + [NSTimer scheduledTimerWithTimeInterval:finishTimer + target:self + selector:@selector(stopBackgroundTask:) + userInfo:nil + repeats:NO]; + + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +} + +-(void)stopBackgroundTask:(NSTimer*)timer +{ + UIApplication *app = [UIApplication sharedApplication]; + + NSLog(@"Push Plugin stopBackgroundTask called"); + + if (handlerObj) { + NSLog(@"Push Plugin handlerObj"); + completionHandler = [handlerObj[@"handler"] copy]; + if (completionHandler) { + NSLog(@"Push Plugin: stopBackgroundTask (remaining t: %f)", app.backgroundTimeRemaining); + completionHandler(UIBackgroundFetchResultNewData); + completionHandler = nil; + } + } +} + +@end diff --git a/StoneIsland/platforms/ios/StoneIsland/StoneIsland-Info.plist b/StoneIsland/platforms/ios/StoneIsland/StoneIsland-Info.plist index 884d2059..160c02b8 100644 --- a/StoneIsland/platforms/ios/StoneIsland/StoneIsland-Info.plist +++ b/StoneIsland/platforms/ios/StoneIsland/StoneIsland-Info.plist @@ -178,5 +178,9 @@ </dict> <key>NSLocationWhenInUseUsageDescription</key> <string></string> + <key>UIBackgroundModes</key> + <array> + <string>remote-notification</string> + </array> </dict> </plist>
\ No newline at end of file diff --git a/StoneIsland/platforms/ios/StoneIsland/config.xml b/StoneIsland/platforms/ios/StoneIsland/config.xml index f2e3c45d..3eaf2fb1 100755 --- a/StoneIsland/platforms/ios/StoneIsland/config.xml +++ b/StoneIsland/platforms/ios/StoneIsland/config.xml @@ -63,4 +63,7 @@ <preference name="StatusBarOverlaysWebView" value="false" /> <preference name="StatusBarBackgroundColor" value="#000000" /> <preference name="StatusBarStyle" value="lightcontent" /> + <feature name="PushNotification"> + <param name="ios-package" value="PushPlugin" /> + </feature> </widget> diff --git a/StoneIsland/platforms/ios/www/cordova_plugins.js b/StoneIsland/platforms/ios/www/cordova_plugins.js index cb7aedde..fbdc76c9 100644 --- a/StoneIsland/platforms/ios/www/cordova_plugins.js +++ b/StoneIsland/platforms/ios/www/cordova_plugins.js @@ -84,6 +84,13 @@ module.exports = [ "clobbers": [ "navigator.splashscreen" ] + }, + { + "file": "plugins/phonegap-plugin-push/www/push.js", + "id": "phonegap-plugin-push.PushNotification", + "clobbers": [ + "PushNotification" + ] } ]; module.exports.metadata = @@ -96,7 +103,8 @@ module.exports.metadata = "cordova-plugin-dialogs": "1.1.1", "cordova-plugin-geolocation": "1.0.1", "cordova-plugin-network-information": "1.0.1", - "cordova-plugin-splashscreen": "2.1.0" + "cordova-plugin-splashscreen": "2.1.0", + "phonegap-plugin-push": "1.4.4" } // BOTTOM OF METADATA });
\ No newline at end of file diff --git a/StoneIsland/platforms/ios/www/plugins/phonegap-plugin-push/www/push.js b/StoneIsland/platforms/ios/www/plugins/phonegap-plugin-push/www/push.js new file mode 100644 index 00000000..7aa30fd7 --- /dev/null +++ b/StoneIsland/platforms/ios/www/plugins/phonegap-plugin-push/www/push.js @@ -0,0 +1,231 @@ +cordova.define("phonegap-plugin-push.PushNotification", function(require, exports, module) { /* global cordova:false */ + +/*! + * Module dependencies. + */ + +var exec = cordova.require('cordova/exec'); + +/** + * PushNotification constructor. + * + * @param {Object} options to initiate Push Notifications. + * @return {PushNotification} instance that can be monitored and cancelled. + */ + +var PushNotification = function(options) { + this._handlers = { + 'registration': [], + 'notification': [], + 'error': [] + }; + + // require options parameter + if (typeof options === 'undefined') { + throw new Error('The options argument is required.'); + } + + // store the options to this object instance + this.options = options; + + // triggered on registration and notification + var that = this; + var success = function(result) { + if (result && typeof result.registrationId !== 'undefined') { + that.emit('registration', result); + } else if (result && typeof result.callback !== 'undefined') { + var executeFunctionByName = function(functionName, context /*, args */) { + var args = Array.prototype.slice.call(arguments, 2); + var namespaces = functionName.split("."); + var func = namespaces.pop(); + for (var i = 0; i < namespaces.length; i++) { + context = context[namespaces[i]]; + } + return context[func].apply(context, args); + } + + executeFunctionByName(result.callback, window, result); + } else if (result) { + that.emit('notification', result); + } + }; + + // triggered on error + var fail = function(msg) { + var e = (typeof msg === 'string') ? new Error(msg) : msg; + that.emit('error', e); + }; + + // wait at least one process tick to allow event subscriptions + setTimeout(function() { + exec(success, fail, 'PushNotification', 'init', [options]); + }, 10); +}; + +/** + * Unregister from push notifications + */ + +PushNotification.prototype.unregister = function(successCallback, errorCallback, options) { + if (errorCallback == null) { errorCallback = function() {}} + + if (typeof errorCallback != "function") { + console.log("PushNotification.unregister failure: failure parameter not a function"); + return + } + + if (typeof successCallback != "function") { + console.log("PushNotification.unregister failure: success callback parameter must be a function"); + return + } + + exec(successCallback, errorCallback, "PushNotification", "unregister", [options]); +}; + +/** + * Call this to set the application icon badge + */ + +PushNotification.prototype.setApplicationIconBadgeNumber = function(successCallback, errorCallback, badge) { + if (errorCallback == null) { errorCallback = function() {}} + + if (typeof errorCallback != "function") { + console.log("PushNotification.setApplicationIconBadgeNumber failure: failure parameter not a function"); + return + } + + if (typeof successCallback != "function") { + console.log("PushNotification.setApplicationIconBadgeNumber failure: success callback parameter must be a function"); + return + } + + exec(successCallback, errorCallback, "PushNotification", "setApplicationIconBadgeNumber", [{badge: badge}]); +}; + +/** + * Get the application icon badge + */ + +PushNotification.prototype.getApplicationIconBadgeNumber = function(successCallback, errorCallback) { + if (errorCallback == null) { errorCallback = function() {}} + + if (typeof errorCallback != "function") { + console.log("PushNotification.getApplicationIconBadgeNumber failure: failure parameter not a function"); + return + } + + if (typeof successCallback != "function") { + console.log("PushNotification.getApplicationIconBadgeNumber failure: success callback parameter must be a function"); + return + } + + exec(successCallback, errorCallback, "PushNotification", "getApplicationIconBadgeNumber", []); +}; + +/** + * Listen for an event. + * + * The following events are supported: + * + * - registration + * - notification + * - error + * + * @param {String} eventName to subscribe to. + * @param {Function} callback triggered on the event. + */ + +PushNotification.prototype.on = function(eventName, callback) { + if (this._handlers.hasOwnProperty(eventName)) { + this._handlers[eventName].push(callback); + } +}; + +/** + * Remove event listener. + * + * @param {String} eventName to match subscription. + * @param {Function} handle function associated with event. + */ + +PushNotification.prototype.off = function (eventName, handle) { + if (this._handlers.hasOwnProperty(eventName)) { + var handleIndex = this._handlers[eventName].indexOf(handle); + if (handleIndex >= 0) + this._handlers[eventName].splice(handleIndex, 1); + } +}; + +/** + * Emit an event. + * + * This is intended for internal use only. + * + * @param {String} eventName is the event to trigger. + * @param {*} all arguments are passed to the event listeners. + * + * @return {Boolean} is true when the event is triggered otherwise false. + */ + +PushNotification.prototype.emit = function() { + var args = Array.prototype.slice.call(arguments); + var eventName = args.shift(); + + if (!this._handlers.hasOwnProperty(eventName)) { + return false; + } + + for (var i = 0, length = this._handlers[eventName].length; i < length; i++) { + this._handlers[eventName][i].apply(undefined,args); + } + + return true; +}; + +PushNotification.prototype.finish = function(successCallback, errorCallback) { + if (successCallback == null) { successCallback = function() {}} + if (errorCallback == null) { errorCallback = function() {}} + + if (typeof successCallback != "function") { + console.log("finish failure: success callback parameter must be a function"); + return + } + + if (typeof errorCallback != "function") { + console.log("finish failure: failure parameter not a function"); + return + } + + exec(successCallback, errorCallback, 'PushNotification', 'finish', []); +} + +/*! + * Push Notification Plugin. + */ + +module.exports = { + /** + * Register for Push Notifications. + * + * This method will instantiate a new copy of the PushNotification object + * and start the registration process. + * + * @param {Object} options + * @return {PushNotification} instance + */ + + init: function(options) { + return new PushNotification(options); + }, + + /** + * PushNotification Object. + * + * Expose the PushNotification object for direct use + * and testing. Typically, you should use the + * .init helper method. + */ + + PushNotification: PushNotification +}; +}); |
