diff --git a/README.md b/README.md index e157d96bf..e9203b21a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This requires phonegap/cordova CLI 5.0+ ( current stable v1.4.2 ) ``` phonegap plugin add phonegap-plugin-push ``` -or +or ``` cordova plugin add phonegap-plugin-push @@ -21,7 +21,7 @@ It is also possible to install via repo url directly ( unstable ) phonegap plugin add https://github.com/phonegap/phonegap-plugin-push ``` -or +or ``` cordova plugin add https://github.com/phonegap/phonegap-plugin-push @@ -202,6 +202,28 @@ successHandler gets called when background push processing is successfully compl push.finish(successHandler, errorHandler); ``` +### PushNotification.hasPermission(callback) + +Checks whether the PushNotification Permission have been enabled or disabled. + +Callback Parameter | Description +------------------ | ----------- +`data.isEnabled` | `Boolean` + +#### Example + +```javascript +PushNotification.hasPermission(function(data) { + if (data.isEnabled) { + var push = PushNotification.init({ + android: { + senderId: 'abc' + } + }); + } +}); +``` + ## PhoneGap Build Support Including this plugin in a project that is built by PhoneGap Build is as easy as adding: @@ -246,10 +268,10 @@ This is because Android now uses Material design and the default icon for push w In order to get a better user experience you can specify an alternate icon and background color to be shown when receiving a push notification. The code would look like this: ```javascript - var push = PushNotification.init({ - "android": { - "senderID": "123456789", "icon": "phonegap", "iconColor": "blue"}, - "ios": {"alert": "true", "badge": "true", "sound": "true"}, "windows": {} + var push = PushNotification.init({ + "android": { + "senderID": "123456789", "icon": "phonegap", "iconColor": "blue"}, + "ios": {"alert": "true", "badge": "true", "sound": "true"}, "windows": {} }); ``` @@ -482,7 +504,7 @@ To add to your app: ``` phonegap plugin add https://github.com/jeduan/cordova-plugin-facebook4 --variable APP_ID="App ID" --variable APP_NAME="App Name" ``` -or +or ``` cordova plugin add https://github.com/jeduan/cordova-plugin-facebook4 --variable APP_ID="App ID" --variable APP_NAME="App Name" @@ -581,7 +603,7 @@ However if you want your `on('notification')` event handler called but no notifi } ``` -That covers what you need to do on the server side to accept background pushes on iOS. However, it is critically important that you continue reading as there will be a change in your `on('notification')`. When you receive a background push on iOS you will be given 30 seconds of time in which to complete a task. If you spend longer than 30 seconds on the task the OS may decide that your app is misbehaving and kill it. In order to signal iOS that your `on('notification')` handler is done you will need to call the new `push.finish()` method. +That covers what you need to do on the server side to accept background pushes on iOS. However, it is critically important that you continue reading as there will be a change in your `on('notification')`. When you receive a background push on iOS you will be given 30 seconds of time in which to complete a task. If you spend longer than 30 seconds on the task the OS may decide that your app is misbehaving and kill it. In order to signal iOS that your `on('notification')` handler is done you will need to call the new `push.finish()` method. For example: @@ -594,11 +616,11 @@ For example: "clearBadge": true } }); - + push.on('registration', function(data) { // send data.registrationId to push service }); - + push.on('notification', function(data) { // do something with the push data @@ -623,11 +645,11 @@ For advanced templates and usage, the notification object is included in [`data. ### Setting Toast Capable Option for Windows -This plugin automatically sets the toast capable flag to be true for Cordova 5.1.1+. For lower versions, you must declare that it is Toast Capable in your app's manifest file. +This plugin automatically sets the toast capable flag to be true for Cordova 5.1.1+. For lower versions, you must declare that it is Toast Capable in your app's manifest file. ### Disabling the default processing of notifications by Windows -The default handling can be disabled by setting the 'cancel' property in the notification object. +The default handling can be disabled by setting the 'cancel' property in the notification object. ``` data.additionalData.pushNotificationReceivedEventArgs.cancel = true diff --git a/plugin.xml b/plugin.xml index 0551434c7..2adee2447 100755 --- a/plugin.xml +++ b/plugin.xml @@ -48,7 +48,7 @@ - + - + @@ -82,6 +82,7 @@ + @@ -93,13 +94,13 @@ - + remote-notification - + diff --git a/src/android/com/adobe/phonegap/push/PermissionUtils.java b/src/android/com/adobe/phonegap/push/PermissionUtils.java new file mode 100644 index 000000000..f7afdd5e1 --- /dev/null +++ b/src/android/com/adobe/phonegap/push/PermissionUtils.java @@ -0,0 +1,56 @@ +package com.adobe.phonegap.push; + +import android.app.AppOpsManager; +import android.content.Context; +import android.content.pm.ApplicationInfo; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class PermissionUtils { + + private static final String CHECK_OP_NO_THROW = "checkOpNoThrow"; + + public static boolean hasPermission(Context appContext, String appOpsServiceId) throws UnknownError { + + AppOpsManager mAppOps = (AppOpsManager) appContext.getSystemService(Context.APP_OPS_SERVICE); + ApplicationInfo appInfo = appContext.getApplicationInfo(); + + String pkg = appContext.getPackageName(); + int uid = appInfo.uid; + Class appOpsClass = null; + + try { + + appOpsClass = Class.forName(AppOpsManager.class.getName()); + + Method checkOpNoThrowMethod = appOpsClass.getMethod( + CHECK_OP_NO_THROW, + Integer.TYPE, + Integer.TYPE, + String.class + ); + + Field opValue = appOpsClass.getDeclaredField(appOpsServiceId); + + int value = (int) opValue.getInt(Integer.class); + Object result = checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg); + + return Integer.parseInt(result.toString()) == AppOpsManager.MODE_ALLOWED; // type madness + + } catch (ClassNotFoundException e) { + throw new UnknownError("class not found"); + } catch (NoSuchMethodException e) { + throw new UnknownError("no such method"); + } catch (NoSuchFieldException e) { + throw new UnknownError("no such field"); + } catch (InvocationTargetException e) { + throw new UnknownError("invocation target"); + } catch (IllegalAccessException e) { + throw new UnknownError("illegal access"); + } + + } + +} diff --git a/src/android/com/adobe/phonegap/push/PushConstants.java b/src/android/com/adobe/phonegap/push/PushConstants.java index 0d02c798e..2e22f4993 100644 --- a/src/android/com/adobe/phonegap/push/PushConstants.java +++ b/src/android/com/adobe/phonegap/push/PushConstants.java @@ -39,6 +39,7 @@ public interface PushConstants { public static final String UNREGISTER = "unregister"; public static final String EXIT = "exit"; public static final String FINISH = "finish"; + public static final String HAS_PERMISSION = "hasPermission"; public static final String ANDROID = "android"; public static final String SENDER_ID = "senderID"; public static final String CLEAR_NOTIFICATIONS = "clearNotifications"; diff --git a/src/android/com/adobe/phonegap/push/PushPlugin.java b/src/android/com/adobe/phonegap/push/PushPlugin.java index d81a06198..74da91a6a 100644 --- a/src/android/com/adobe/phonegap/push/PushPlugin.java +++ b/src/android/com/adobe/phonegap/push/PushPlugin.java @@ -152,6 +152,22 @@ public void run() { }); } else if (FINISH.equals(action)) { callbackContext.success(); + } else if (HAS_PERMISSION.equals(action)) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + JSONObject jo = new JSONObject(); + try { + jo.put("isEnabled", PermissionUtils.hasPermission(getApplicationContext(), "OP_POST_NOTIFICATION")); + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, jo); + pluginResult.setKeepCallback(true); + callbackContext.sendPluginResult(pluginResult); + } catch (UnknownError e) { + callbackContext.error(e.getMessage()); + } catch (JSONException e) { + callbackContext.error(e.getMessage()); + } + } + }); } else { Log.e(LOG_TAG, "Invalid action : " + action); callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION)); @@ -240,7 +256,7 @@ private static JSONObject convertBundleToJson(Bundle extras) { while (it.hasNext()) { String key = it.next(); Object value = extras.get(key); - + Log.d(LOG_TAG, "key = " + key); if (jsonKeySet.contains(key)) { @@ -265,7 +281,7 @@ else if (strValue.startsWith("[")) { } else { additionalData.put(key, value); - } + } } catch (Exception e) { additionalData.put(key, value); } @@ -290,4 +306,4 @@ public static boolean isInForeground() { public static boolean isActive() { return gWebView != null; } -} \ No newline at end of file +} diff --git a/src/ios/AppDelegate+notification.m b/src/ios/AppDelegate+notification.m index 8b4ed161b..55c96c86f 100644 --- a/src/ios/AppDelegate+notification.m +++ b/src/ios/AppDelegate+notification.m @@ -72,13 +72,13 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N 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"]; @@ -88,7 +88,7 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N } else if ([contentAvailable isKindOfClass:[NSNumber class]]) { silent = [contentAvailable integerValue]; } - + if (silent == 1) { NSLog(@"this should be a silent push"); void (^safeHandler)(UIBackgroundFetchResult) = ^(UIBackgroundFetchResult result){ @@ -96,10 +96,10 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N completionHandler(result); }); }; - + NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:2]; [params setObject:safeHandler forKey:@"handler"]; - + PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; pushHandler.notificationMessage = userInfo; pushHandler.isInline = NO; @@ -109,12 +109,24 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N NSLog(@"just put it in the shade"); //save it for later self.launchNotification = userInfo; - + completionHandler(UIBackgroundFetchResultNewData); } } } +- (BOOL)userHasRemoteNotificationsEnabled { + UIApplication *application = [UIApplication sharedApplication]; + if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) { + return application.currentUserNotificationSettings.types != UIUserNotificationTypeNone; + } else { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + return application.enabledRemoteNotificationTypes != UIRemoteNotificationTypeNone; +#pragma GCC diagnostic pop + } +} + - (void)applicationDidBecomeActive:(UIApplication *)application { NSLog(@"active"); @@ -123,7 +135,7 @@ - (void)applicationDidBecomeActive:(UIApplication *)application { if (pushHandler.clearBadge) { NSLog(@"PushPlugin clearing badge"); //zero badge - application.applicationIconBadgeNumber = 0; + application.applicationIconBadgeNumber = 0; } else { NSLog(@"PushPlugin skip clear badge"); } diff --git a/src/ios/PushPlugin.m b/src/ios/PushPlugin.m index 40f494d14..473d242d5 100644 --- a/src/ios/PushPlugin.m +++ b/src/ios/PushPlugin.m @@ -1,16 +1,16 @@ /* 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 @@ -39,7 +39,7 @@ @implementation PushPlugin - (void)unregister:(CDVInvokedUrlCommand*)command; { self.callbackId = command.callbackId; - + [[UIApplication sharedApplication] unregisterForRemoteNotifications]; [self successWithMessage:@"unregistered"]; } @@ -47,23 +47,23 @@ - (void)unregister:(CDVInvokedUrlCommand*)command; - (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; @@ -71,7 +71,7 @@ - (void)init:(CDVInvokedUrlCommand*)command; UserNotificationTypes |= UIUserNotificationTypeBadge; #endif } - + if (([soundArg isKindOfClass:[NSString class]] && [soundArg isEqualToString:@"true"]) || [soundArg boolValue]) { notificationTypes |= UIRemoteNotificationTypeSound; @@ -79,7 +79,7 @@ - (void)init:(CDVInvokedUrlCommand*)command; UserNotificationTypes |= UIUserNotificationTypeSound; #endif } - + if (([alertArg isKindOfClass:[NSString class]] && [alertArg isEqualToString:@"true"]) || [alertArg boolValue]) { notificationTypes |= UIRemoteNotificationTypeAlert; @@ -87,12 +87,12 @@ - (void)init:(CDVInvokedUrlCommand*)command; 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; @@ -102,12 +102,12 @@ - (void)init:(CDVInvokedUrlCommand*)command; [[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]; @@ -121,7 +121,7 @@ - (void)init:(CDVInvokedUrlCommand*)command; [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; #endif - + if (notificationMessage) // if there is a pending startup notification [self notificationReceived]; // go ahead and process it @@ -134,33 +134,33 @@ - (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)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 @@ -174,17 +174,17 @@ - (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 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"]; @@ -206,21 +206,21 @@ - (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)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) { @@ -253,20 +253,20 @@ - (void)notificationReceived { [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; } } @@ -275,9 +275,9 @@ - (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]; @@ -291,6 +291,20 @@ - (void)getApplicationIconBadgeNumber:(CDVInvokedUrlCommand *)command [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; } +- (void)hasPermission:(CDVInvokedUrlCommand *)command +{ + BOOL enabled = NO; + id appDelegate = [UIApplication sharedApplication].delegate; + if ([appDelegate respondsToSelector:@selector(userHasRemoteNotificationsEnabled)]) { + enabled = [appDelegate performSelector:@selector(userHasRemoteNotificationsEnabled)]; + } + + NSMutableDictionary* message = [NSMutableDictionary dictionaryWithCapacity:1]; + [message setObject:[NSNumber numberWithBool:enabled] forKey:@"isEnabled"]; + CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:message]; + [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; +} + -(void)successWithMessage:(NSString *)message { if (self.callbackId != nil) @@ -304,7 +318,7 @@ -(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]; } @@ -315,7 +329,7 @@ -(void) finish:(CDVInvokedUrlCommand*)command [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:) @@ -330,9 +344,9 @@ -(void) finish:(CDVInvokedUrlCommand*)command -(void)stopBackgroundTask:(NSTimer*)timer { UIApplication *app = [UIApplication sharedApplication]; - + NSLog(@"Push Plugin stopBackgroundTask called"); - + if (handlerObj) { NSLog(@"Push Plugin handlerObj"); completionHandler = [handlerObj[@"handler"] copy]; diff --git a/www/push.js b/www/push.js index 139009457..033a4ece7 100644 --- a/www/push.js +++ b/www/push.js @@ -43,7 +43,7 @@ var PushNotification = function(options) { } return context[func].apply(context, args); } - + executeFunctionByName(result.callback, window, result); } else if (result) { that.emit('notification', result); @@ -101,24 +101,24 @@ PushNotification.prototype.setApplicationIconBadgeNumber = function(successCallb 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", []); }; @@ -170,12 +170,12 @@ PushNotification.prototype.emit = function() { 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 @@ -183,7 +183,7 @@ PushNotification.prototype.finish = function(successCallback, errorCallback) { exec(successCallback, errorCallback, 'PushNotification', 'finish', []); } - + /*! * Push Notification Plugin. */ @@ -203,6 +203,10 @@ module.exports = { return new PushNotification(options); }, + hasPermission: function(successCallback, errorCallback) { + exec(successCallback, errorCallback, 'PushNotification', 'hasPermission', []); + }, + /** * PushNotification Object. * @@ -212,4 +216,4 @@ module.exports = { */ PushNotification: PushNotification -}; \ No newline at end of file +};