Commit bafe8b5e by PKnittel
parents 8a3ca729 f0f3d4c0
## ChangeLog ## ChangeLog
#### Version 0.8.0 (not yet released) #### Version 0.8.0 (not yet released)
- [feature:] New method `hasPermission` to ask if the user has granted to display local notifications.
- [feature:] New method `registerPermission` to register permission to display local notifications.
- [feature:] New Android specific `led:` flag.
- [feature:] Add `isTriggered` & `getTriggeredIds` methods.
- [enhancement:] iOS8 support.
- [enhancement:] Android 2.x (SDK >= 7) support (Thanks to **khizarsonu**) - [enhancement:] Android 2.x (SDK >= 7) support (Thanks to **khizarsonu**)
- [enhancement:] Scope parameter for `isScheduled` and `getScheduledIds` - [enhancement:] Scope parameter for `isScheduled` and `getScheduledIds`
- [enhancement:] Callbacks for `add`, `cancel` & `cancelAll` - [enhancement:] Callbacks for `add`, `cancel` & `cancelAll`
- [enhancement:] `image:` accepts remote URLs and local URIs (Android) - [enhancement:] `image:` accepts remote URLs and local URIs (Android)
- [feature:] New Android specific `led:` flag.
- [feature:] Add `isTriggered` & `getTriggeredIds` methods.
#### Version 0.7.4 (22.03.2014) #### Version 0.7.4 (22.03.2014)
- [bugfix:] Platform specific properties were ignored. - [bugfix:] Platform specific properties were ignored.
......
...@@ -19,7 +19,7 @@ The purpose of the plugin is to create an platform independent javascript interf ...@@ -19,7 +19,7 @@ The purpose of the plugin is to create an platform independent javascript interf
## Supported Platforms ## Supported Platforms
- **iOS**<br> - **iOS** _(up to iOS8)_<br>
See [Local and Push Notification Programming Guide][ios_notification_guide] for detailed informations and screenshots. See [Local and Push Notification Programming Guide][ios_notification_guide] for detailed informations and screenshots.
- **Android** *(SDK >=7)*<br> - **Android** *(SDK >=7)*<br>
...@@ -70,12 +70,15 @@ More informations can be found [here][PGB_plugin]. ...@@ -70,12 +70,15 @@ More informations can be found [here][PGB_plugin].
## ChangeLog ## ChangeLog
#### Version 0.8.0 (not yet released) #### Version 0.8.0 (not yet released)
- [feature:] New method `hasPermission` to ask if the user has granted to display local notifications.
- [feature:] New method `registerPermission` to register permission to display local notifications.
- [feature:] New Android specific `led:` flag.
- [feature:] Add `isTriggered` & `getTriggeredIds` methods.
- [enhancement:] iOS8 support.
- [enhancement:] Android 2.x (SDK >= 7) support (Thanks to **khizarsonu**) - [enhancement:] Android 2.x (SDK >= 7) support (Thanks to **khizarsonu**)
- [enhancement:] Scope parameter for `isScheduled` and `getScheduledIds` - [enhancement:] Scope parameter for `isScheduled` and `getScheduledIds`
- [enhancement:] Callbacks for `add`, `cancel` & `cancelAll` - [enhancement:] Callbacks for `add`, `cancel` & `cancelAll`
- [enhancement:] `image:` accepts remote URLs and local URIs (Android) - [enhancement:] `image:` accepts remote URLs and local URIs (Android)
- [feature:] New Android specific `led:` flag
- [feature:] Add `isTriggered` & `getTriggeredIds` methods.
#### Further informations #### Further informations
- See [CHANGELOG.md][changelog] to get the full changelog for the plugin. - See [CHANGELOG.md][changelog] to get the full changelog for the plugin.
...@@ -85,18 +88,20 @@ More informations can be found [here][PGB_plugin]. ...@@ -85,18 +88,20 @@ More informations can be found [here][PGB_plugin].
## Using the plugin ## Using the plugin
The plugin creates the object ```window.plugin.notification.local``` with the following methods: The plugin creates the object ```window.plugin.notification.local``` with the following methods:
1. [notification.local.add][add] 1. [notification.local.hasPermission][has_permission]
2. [notification.local.cancel][cancel] 2. [notification.local.registerPermission][register_permission]
3. [notification.local.cancelAll][cancelall] 3. [notification.local.add][add]
4. [notification.local.isScheduled][isscheduled] 4. [notification.local.cancel][cancel]
5. [notification.local.getScheduledIds][getscheduledids] 5. [notification.local.cancelAll][cancelall]
6. [notification.local.isTriggered][istriggered] 6. [notification.local.isScheduled][isscheduled]
7. [notification.local.getDefaults][getdefaults] 7. [notification.local.getScheduledIds][getscheduledids]
8. [notification.local.setDefaults][setDefaults] 8. [notification.local.isTriggered][istriggered]
9. [notification.local.onadd][onadd] 9. [notification.local.getDefaults][getdefaults]
10. [notification.local.ontrigger][ontrigger] 10. [notification.local.setDefaults][setdefaults]
11. [notification.local.onclick][onclick] 11. [notification.local.onadd][onadd]
12. [notification.local.oncancel][oncancel] 12. [notification.local.ontrigger][ontrigger]
13. [notification.local.onclick][onclick]
14. [notification.local.oncancel][oncancel]
### Plugin initialization ### Plugin initialization
The plugin and its methods are not available before the *deviceready* event has been fired. The plugin and its methods are not available before the *deviceready* event has been fired.
...@@ -107,6 +112,30 @@ document.addEventListener('deviceready', function () { ...@@ -107,6 +112,30 @@ document.addEventListener('deviceready', function () {
}, false); }, false);
``` ```
### Determine if the app does have the permission to show local notifications
If the permission has been granted through the user can be retrieved through the `notification.local.hasPermission` interface.<br/>
The method takes a callback function as its argument which will be called with a boolean value. Optional the scope of the callback function ca be defined through a second argument.
#### Further informations
- The method is supported on each platform, however its only relevant for iOS8 and above.
```javascript
window.plugin.notification.local.hasPermission(function (granted) {
// console.log('Permission has been granted: ' + granted);
});
```
### Register permission for local notifications
Required permissions can be registered through the `notification.local.registerPermission` interface.
#### Further informations
- The method is supported on each platform, however its only relevant for iOS8 and above.
- The user will only get a prompt dialog for the first time. Later its only possible to change the setting via the notification center.
```javascript
window.plugin.notification.local.registerPermission();
```
### Schedule local notifications ### Schedule local notifications
Local notifications can be scheduled through the `notification.local.add` interface.<br> Local notifications can be scheduled through the `notification.local.add` interface.<br>
The method takes a hash as an argument to specify the notification's properties and returns the ID for the notification.<br> The method takes a hash as an argument to specify the notification's properties and returns the ID for the notification.<br>
...@@ -533,6 +562,8 @@ This software is released under the [Apache 2.0 License][apache2_license]. ...@@ -533,6 +562,8 @@ This software is released under the [Apache 2.0 License][apache2_license].
[oncancel]: #get-notified-when-a-local-notification-has-been-canceled [oncancel]: #get-notified-when-a-local-notification-has-been-canceled
[ontrigger]: #get-notified-when-a-local-notification-has-been-triggered [ontrigger]: #get-notified-when-a-local-notification-has-been-triggered
[platform-specific-properties]: #platform-specifics [platform-specific-properties]: #platform-specifics
[has_permission]: #determine-if-the-app-does-have-the-permission-to-show-local-notifications
[register_permission]: #register-permission-for-local-notifications
[add]: #schedule-local-notifications [add]: #schedule-local-notifications
[cancel]: #cancel-scheduled-local-notifications [cancel]: #cancel-scheduled-local-notifications
[cancelall]: #cancel-all-scheduled-local-notifications [cancelall]: #cancel-all-scheduled-local-notifications
......
...@@ -35,6 +35,15 @@ ...@@ -35,6 +35,15 @@
<header-file src="src/ios/APPLocalNotification.h" /> <header-file src="src/ios/APPLocalNotification.h" />
<source-file src="src/ios/APPLocalNotification.m" /> <source-file src="src/ios/APPLocalNotification.m" />
<header-file src="src/ios/APPLocalNotificationOptions.h" />
<source-file src="src/ios/APPLocalNotificationOptions.m" />
<source-file src="src/ios/UIApplication+APPLocalNotification.h" />
<source-file src="src/ios/UIApplication+APPLocalNotification.m" />
<header-file src="src/ios/UILocalNotification+APPLocalNotification.h" />
<source-file src="src/ios/UILocalNotification+APPLocalNotification.m" />
</platform> </platform>
<!-- android --> <!-- android -->
......
...@@ -36,5 +36,9 @@ ...@@ -36,5 +36,9 @@
- (void) isScheduled:(CDVInvokedUrlCommand*)command; - (void) isScheduled:(CDVInvokedUrlCommand*)command;
// Retrieves a list of ids from all currently pending notifications // Retrieves a list of ids from all currently pending notifications
- (void) getScheduledIds:(CDVInvokedUrlCommand*)command; - (void) getScheduledIds:(CDVInvokedUrlCommand*)command;
// Informs if the app has the permission to show notifications
- (void) hasPermission:(CDVInvokedUrlCommand*)command;
// Registers permission to show notifications
- (void) registerPermission:(CDVInvokedUrlCommand*)command;
@end @end
...@@ -20,11 +20,14 @@ ...@@ -20,11 +20,14 @@
*/ */
#import "APPLocalNotification.h" #import "APPLocalNotification.h"
#import "APPLocalNotificationOptions.h"
#import "UIApplication+APPLocalNotification.h"
#import "UILocalNotification+APPLocalNotification.h"
#import <Availability.h>
@interface APPLocalNotification () @interface APPLocalNotification ()
// Retrieves all scheduled notifications
@property (readonly, getter=scheduledNotifications) NSArray* scheduledNotifications;
// Retrieves the application state // Retrieves the application state
@property (readonly, getter=applicationState) NSString* applicationState; @property (readonly, getter=applicationState) NSString* applicationState;
// All events will be queued until deviceready has been fired // All events will be queued until deviceready has been fired
...@@ -36,13 +39,13 @@ ...@@ -36,13 +39,13 @@
@implementation APPLocalNotification @implementation APPLocalNotification
@synthesize deviceready, eventQueue, applicationState, scheduledNotifications; @synthesize deviceready, eventQueue;
#pragma mark - #pragma mark -
#pragma mark Plugin interface methods #pragma mark Interface
/** /**
* Executes all queued events. * Execute all queued events.
*/ */
- (void) deviceready:(CDVInvokedUrlCommand*)command - (void) deviceready:(CDVInvokedUrlCommand*)command
{ {
...@@ -56,29 +59,24 @@ ...@@ -56,29 +59,24 @@
} }
/** /**
* Schedules a new local notification. * Schedule a new local notification.
* *
* @param {NSMutableDictionary} properties * @param properties
* The properties of the notification * A dict of properties
*/ */
- (void) add:(CDVInvokedUrlCommand*)command - (void) add:(CDVInvokedUrlCommand*)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
NSArray* arguments = [command arguments]; NSDictionary* options = [[command arguments]
NSMutableDictionary* properties = [arguments objectAtIndex:0]; objectAtIndex:0];
NSString* id = [properties objectForKey:@"id"];
if ([self isNotificationScheduledWithId:id]) { UILocalNotification* notification;
UILocalNotification* notification = [self notificationWithId:id];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), notification = [[UILocalNotification alloc]
dispatch_get_main_queue(), ^{ initWithOptions:options];
[self cancelNotification:notification fireEvent:NO];
});
}
[self scheduleNotificationWithProperties:properties]; [self scheduleLocalNotification:notification];
[self fireEvent:@"add" localNotification:notification];
[self execCallback:command]; [self execCallback:command];
}]; }];
} }
...@@ -86,21 +84,22 @@ ...@@ -86,21 +84,22 @@
/** /**
* Cancels a given local notification. * Cancels a given local notification.
* *
* @param {NSString} id * @param id
* The ID of the local notification * The ID of the local notification
*/ */
- (void) cancel:(CDVInvokedUrlCommand*)command - (void) cancel:(CDVInvokedUrlCommand*)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
NSArray* arguments = [command arguments]; NSString* id = [[command arguments]
NSString* id = [arguments objectAtIndex:0]; objectAtIndex:0];
UILocalNotification* notification = [self notificationWithId:id]; UILocalNotification* notification;
if (notification) { notification = [[UIApplication sharedApplication]
[self cancelNotification:notification fireEvent:YES]; scheduledLocalNotificationWithId:id];
}
[self cancelLocalNotification:notification];
[self fireEvent:@"cancel" localNotification:notification];
[self execCallback:command]; [self execCallback:command];
}]; }];
} }
...@@ -111,37 +110,31 @@ ...@@ -111,37 +110,31 @@
- (void) cancelAll:(CDVInvokedUrlCommand*)command - (void) cancelAll:(CDVInvokedUrlCommand*)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
NSArray* notifications = self.scheduledNotifications; [self cancelAllLocalNotifications];
[self fireEvent:@"cancelall"];
for (UILocalNotification* notification in notifications) {
[self cancelNotification:notification fireEvent:YES];
}
[[UIApplication sharedApplication]
cancelAllLocalNotifications];
[[UIApplication sharedApplication]
setApplicationIconBadgeNumber:0];
[self execCallback:command]; [self execCallback:command];
}]; }];
} }
/** /**
* Checks wether a notification with an ID is scheduled. * If a notification by ID is scheduled.
* *
* @param {NSString} id * @param id
* The ID of the notification * The ID of the notification
* @param callback
* The callback function to be called with the result
*/ */
- (void) isScheduled:(CDVInvokedUrlCommand*)command - (void) isScheduled:(CDVInvokedUrlCommand*)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
NSArray* arguments = [command arguments]; NSString* id = [[command arguments]
NSString* id = [arguments objectAtIndex:0]; objectAtIndex:0];
bool isScheduled = [self isNotificationScheduledWithId:id];
CDVPluginResult* result; CDVPluginResult* result;
UILocalNotification* notification;
notification = [[UIApplication sharedApplication]
scheduledLocalNotificationWithId:id];
bool isScheduled = notification != NULL;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:isScheduled]; messageAsBool:isScheduled];
...@@ -152,25 +145,16 @@ ...@@ -152,25 +145,16 @@
} }
/** /**
* Retrieves a list of ids from all currently pending notifications. * List of ids from all currently pending notifications.
*
* @param callback
* The callback function to be called with the result
*/ */
- (void) getScheduledIds:(CDVInvokedUrlCommand*)command - (void) getScheduledIds:(CDVInvokedUrlCommand*)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
NSArray* notifications = self.scheduledNotifications;
NSMutableArray* scheduledIds = [[NSMutableArray alloc] init];
CDVPluginResult* result; CDVPluginResult* result;
NSArray* scheduledIds;
for (UILocalNotification* notification in notifications) scheduledIds = [[UIApplication sharedApplication]
{ scheduledLocalNotificationIds];
NSString* id = [notification.userInfo objectForKey:@"id"];
[scheduledIds addObject:id];
}
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:scheduledIds]; messageAsArray:scheduledIds];
...@@ -183,18 +167,22 @@ ...@@ -183,18 +167,22 @@
/** /**
* Checks wether a notification with an ID was triggered. * Checks wether a notification with an ID was triggered.
* *
* @param {NSString} id * @param id
* The ID of the notification * The ID of the notification
* @param callback
* The callback function to be called with the result
*/ */
- (void) isTriggered:(CDVInvokedUrlCommand*)command - (void) isTriggered:(CDVInvokedUrlCommand*)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
NSArray* arguments = [command arguments]; NSString* id = [[command arguments]
NSString* id = [arguments objectAtIndex:0]; objectAtIndex:0];
bool isTriggered = [self isNotificationTriggeredWithId:id];
CDVPluginResult* result; CDVPluginResult* result;
UILocalNotification* notification;
notification = [[UIApplication sharedApplication]
triggeredLocalNotificationWithId:id];
bool isTriggered = notification != NULL;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:isTriggered]; messageAsBool:isTriggered];
...@@ -206,163 +194,155 @@ ...@@ -206,163 +194,155 @@
/** /**
* Retrieves a list of ids from all currently triggered notifications. * Retrieves a list of ids from all currently triggered notifications.
*
* @param callback
* The callback function to be called with the result
*/ */
- (void) getTriggeredIds:(CDVInvokedUrlCommand*)command - (void) getTriggeredIds:(CDVInvokedUrlCommand*)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
NSArray* notifications = self.scheduledNotifications;
NSMutableArray* scheduledIds = [[NSMutableArray alloc] init];
CDVPluginResult* result; CDVPluginResult* result;
NSArray* triggeredIds;
for (UILocalNotification* notification in notifications) triggeredIds = [[UIApplication sharedApplication]
{ triggeredLocalNotificationIds];
if (![self isNotificationTriggered:notification]) {
continue;
}
NSString* id = [notification.userInfo objectForKey:@"id"]; result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:triggeredIds];
[scheduledIds addObject:id]; [self.commandDelegate sendPluginResult:result
} callbackId:command.callbackId];
}];
}
/**
* Inform if the app has the permission to show
* badges and local notifications.
*/
- (void) hasPermission:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
CDVPluginResult* result;
BOOL hasPermission;
hasPermission = [[UIApplication sharedApplication]
hasPermissionToScheduleLocalNotifications];
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:scheduledIds]; messageAsBool:hasPermission];
[self.commandDelegate sendPluginResult:result [self.commandDelegate sendPluginResult:result
callbackId:command.callbackId]; callbackId:command.callbackId];
}]; }];
} }
/**
* Ask for permission to show badges.
*/
- (void) registerPermission:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
[[UIApplication sharedApplication]
registerPermissionToScheduleLocalNotifications];
}];
}
#pragma mark - #pragma mark -
#pragma mark Plugin core methods #pragma mark Core Logic
/** /**
* Schedules a new local notification and fies the coresponding event. * Schedule the local notification.
*
* @param {NSMutableDictionary} properties
* The properties of the notification
*/ */
- (void) scheduleNotificationWithProperties:(NSMutableDictionary*)properties - (void) scheduleLocalNotification:(UILocalNotification*)notification
{ {
UILocalNotification* notification = [self notificationWithProperties: [self cancelForerunnerLocalNotification:notification];
properties];
NSDictionary* userInfo = notification.userInfo; NSString* state = self.applicationState;
NSString* id = [userInfo objectForKey:@"id"];
NSString* json = [userInfo objectForKey:@"json"];
[self fireEvent:@"add" id:id json:json]; if ([state isEqualToString:@"background"]) {
[[UIApplication sharedApplication]
presentLocalNotificationNow:notification];
}
[[UIApplication sharedApplication] [[UIApplication sharedApplication]
scheduleLocalNotification:notification]; scheduleLocalNotification:notification];
} }
/** /**
* Cancels the given local notification * Cancel the local notification.
* and fires the cancel event.
*
* @param {NSString} id
* The ID of the local notification
*/ */
- (void) cancelNotification:(UILocalNotification*)notification - (void) cancelLocalNotification:(UILocalNotification*)notification
fireEvent:(BOOL)fireEvent
{ {
NSDictionary* userInfo = notification.userInfo; if (!notification)
NSString* id = [userInfo objectForKey:@"id"]; return;
NSString* json = [userInfo objectForKey:@"json"];
if (notification==nil) {
NSLog(@"cancelNotification: Notification equals nil");
}else{
[[UIApplication sharedApplication]
cancelLocalNotification:notification];
}
if (fireEvent) { [[UIApplication sharedApplication]
[self fireEvent:@"cancel" id:id json:json]; cancelLocalNotification:notification];
}
} }
/** /**
* Cancels all local notification with are older then * Cancel all currently scheduled notifications.
* a specific amount of seconds
*
* @param {float} seconds
* The time interval in seconds
*/ */
- (void) cancelAllNotificationsWhichAreOlderThen:(float)seconds - (void) cancelAllLocalNotifications
{ {
NSDate* now = [NSDate date]; NSArray* notifications;
NSArray* notifications = self.scheduledNotifications; notifications = [[UIApplication sharedApplication]
scheduledLocalNotifications];
for (UILocalNotification* notification in notifications) for (UILocalNotification* notification in notifications) {
{ [self cancelLocalNotification:notification];
NSDate* fireDate = notification.fireDate;
NSTimeInterval fireDateDistance = [now timeIntervalSinceDate:
fireDate];
if (notification.repeatInterval == NSCalendarUnitEra
&& fireDateDistance > seconds) {
[self cancelNotification:notification fireEvent:YES];
}
} }
[[UIApplication sharedApplication]
cancelAllLocalNotifications];
[[UIApplication sharedApplication]
setApplicationIconBadgeNumber:0];
} }
/** /**
* Creates an notification object based on the given properties. * Cancel a maybe given forerunner with the same ID.
*
* @param {NSMutableDictionary} properties
* The properties for the local notification
* @return {UILocalNotification}
*/ */
- (UILocalNotification*) notificationWithProperties:(NSMutableDictionary*)options - (void) cancelForerunnerLocalNotification:(UILocalNotification*)notification
{ {
UILocalNotification* notification = [[UILocalNotification alloc] init]; NSString* id = notification.options.id;
UILocalNotification* forerunner;
double timestamp = [[options objectForKey:@"date"] doubleValue]; forerunner = [[UIApplication sharedApplication]
NSString* msg = [options objectForKey:@"message"]; scheduledLocalNotificationWithId:id];
NSString* title = [options objectForKey:@"title"];
NSString* sound = [options objectForKey:@"sound"];
NSString* repeat = [options objectForKey:@"repeat"];
NSInteger badge = [[options objectForKey:@"badge"] intValue];
notification.fireDate = [NSDate dateWithTimeIntervalSince1970:timestamp]; if (!forerunner)
notification.timeZone = [NSTimeZone defaultTimeZone]; return;
notification.userInfo = [self userDict:options];
notification.applicationIconBadgeNumber = badge;
notification.repeatInterval = [[[self repeatDict] objectForKey:repeat] [self cancelLocalNotification:forerunner];
intValue]; }
if (![self stringIsNullOrEmpty:msg])
{
if (![self stringIsNullOrEmpty:title]) {
notification.alertBody = [NSString stringWithFormat:
@"%@\n%@", title, msg];
} else {
notification.alertBody = msg;
}
}
if (sound != (NSString*)[NSNull null]) /**
* Cancels all local notification with are older then
* a specific amount of seconds
*
* @param {float} seconds
* The time interval in seconds
*/
- (void) cancelAllNotificationsWhichAreOlderThen:(float)seconds
{
NSArray* notifications;
notifications = [[UIApplication sharedApplication]
scheduledLocalNotifications];
for (UILocalNotification* notification in notifications)
{ {
if ([sound isEqualToString:@""]) { if (notification && notification.repeatInterval == NSCalendarUnitEra
notification.soundName = UILocalNotificationDefaultSoundName; && notification.timeIntervalSinceFireDate > seconds)
} else { {
notification.soundName = sound; [self cancelLocalNotification:notification];
[self fireEvent:@"cancel" localNotification:notification];
} }
} }
return notification;
} }
#pragma mark - #pragma mark -
#pragma mark Plugin delegate and life cycle methods #pragma mark Delegates
/** /**
* Calls the cancel or trigger event after a local notification was received. * Calls the cancel or trigger event after a local notification was received.
...@@ -370,38 +350,36 @@ ...@@ -370,38 +350,36 @@
*/ */
- (void) didReceiveLocalNotification:(NSNotification*)localNotification - (void) didReceiveLocalNotification:(NSNotification*)localNotification
{ {
UIApplication* app = [UIApplication sharedApplication];
UILocalNotification* notification = [localNotification object]; UILocalNotification* notification = [localNotification object];
NSDictionary* userInfo = notification.userInfo; BOOL autoCancel = notification.options.autoCancel;
NSString* id = [userInfo objectForKey:@"id"]; NSTimeInterval timeInterval = notification.timeIntervalSinceFireDate;
NSString* json = [userInfo objectForKey:@"json"];
BOOL autoCancel = [[userInfo objectForKey:@"autoCancel"] boolValue];
NSDate* now = [NSDate date]; NSString* event = (timeInterval <= 1 && deviceready) ? @"trigger" : @"click";
NSDate* fireDate = notification.fireDate;
NSTimeInterval fireDateDistance = [now timeIntervalSinceDate:fireDate];
NSString* event = (fireDateDistance < 1) ? @"trigger" : @"click";
if ([[self applicationState] isEqualToString:@"foreground"]) { app.applicationIconBadgeNumber -= 1;
event = @"trigger";
} [self fireEvent:event localNotification:notification];
if (autoCancel && [event isEqualToString:@"click"]) { if (autoCancel && [event isEqualToString:@"click"]) {
[self cancelNotification:notification fireEvent:YES]; [self cancelLocalNotification:notification];
[self fireEvent:@"cancel" localNotification:notification];
} }
[self fireEvent:event id:id json:json];
} }
/** /**
* Calls the cancel or trigger event after a local notification was received. * Called when app has started
* (by clicking on a local notification).
*/ */
- (void) didFinishLaunchingWithOptions:(NSNotification*)notification - (void) didFinishLaunchingWithOptions:(NSNotification*)notification
{ {
NSDictionary* launchOptions = [notification userInfo]; NSDictionary* launchOptions = [notification userInfo];
UILocalNotification* localNotification = [launchOptions objectForKey: UILocalNotification* localNotification;
UIApplicationLaunchOptionsLocalNotificationKey];
localNotification = [launchOptions objectForKey:
UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotification) { if (localNotification) {
[self didReceiveLocalNotification: [self didReceiveLocalNotification:
...@@ -410,6 +388,9 @@ ...@@ -410,6 +388,9 @@
} }
} }
#pragma mark -
#pragma mark Life Cycle
/** /**
* Registers obervers for the following events after plugin was initialized. * Registers obervers for the following events after plugin was initialized.
* didReceiveLocalNotification: * didReceiveLocalNotification:
...@@ -417,8 +398,10 @@ ...@@ -417,8 +398,10 @@
*/ */
- (void) pluginInitialize - (void) pluginInitialize
{ {
NSNotificationCenter* notificationCenter = [NSNotificationCenter NSNotificationCenter* notificationCenter;
defaultCenter];
notificationCenter = [NSNotificationCenter
defaultCenter];
eventQueue = [[NSMutableArray alloc] init]; eventQueue = [[NSMutableArray alloc] init];
...@@ -443,153 +426,12 @@ ...@@ -443,153 +426,12 @@
} }
#pragma mark - #pragma mark -
#pragma mark Plugin helper methods #pragma mark Helper
/**
* Retrurns a key-value dictionary for repeat intervals.
*
* @return {NSMutableDictionary}
*/
- (NSMutableDictionary*) repeatDict
{
NSMutableDictionary* repeatDict = [[NSMutableDictionary alloc] init];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitSecond] forKey:@"secondly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitMinute] forKey:@"minutely"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitHour] forKey:@"hourly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitDay] forKey:@"daily"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitWeekOfYear] forKey:@"weekly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitMonth] forKey:@"monthly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitYear] forKey:@"yearly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitEra] forKey:@""];
return repeatDict;
}
/**
* Returns the userDict for a local notification.
*
* @param {NSMutableDictionary} options
* The properties for the local notification
* @return {NSDictionary}
*/
- (NSDictionary*) userDict:(NSMutableDictionary*)options
{
NSString* id = [options objectForKey:@"id"];
NSString* ac = [options objectForKey:@"autoCancel"];
NSString* js = [options objectForKey:@"json"];
return [NSDictionary dictionaryWithObjectsAndKeys:
id, @"id", ac, @"autoCancel", js, @"json", nil];
}
/**
* Checks weather the given string is empty or not.
*
* @param {NSString} str The string to be check
* @return {BOOL}
*/
- (BOOL) stringIsNullOrEmpty:(NSString*)str
{
if (str == (NSString*)[NSNull null]) {
return YES;
}
if ([str isEqualToString:@""]) {
return YES;
}
return NO;
}
/**
* Checks wether a notification with an ID is scheduled or not.
*
* @param id
* The ID of the notification
* @return BOOL
*/
- (BOOL) isNotificationScheduledWithId:(NSString*)id
{
UILocalNotification* notification = [self notificationWithId:id];
return notification != NULL;
}
/**
* Checks wether a notification with an ID was triggered or not.
*
* @param id
* The ID of the notification
* @return BOOL
*/
- (BOOL) isNotificationTriggeredWithId:(NSString*)id
{
UILocalNotification* notification = [self notificationWithId:id];
if (notification == NULL) {
return NO;
}
return [self isNotificationTriggered:notification];
}
/**
* Checks wether a notification was triggered or not.
*
* @param notification
* The notification
* @return BOOL
*/
- (BOOL) isNotificationTriggered:(UILocalNotification*)notification
{
NSDate* now = [NSDate date];
NSDate* fireDate = notification.fireDate;
bool isLaterThanOrEqualTo = !([now compare:fireDate] == NSOrderedAscending);
return isLaterThanOrEqualTo;
}
/**
* Retrieves the local notification by its ID.
*
* @param {NSString} id
* The ID of the notification
* @return UILocalNotification*
*/
- (UILocalNotification*) notificationWithId:(NSString*)id
{
NSArray* notifications = self.scheduledNotifications;
for (UILocalNotification* notification in notifications)
{
NSString* notId = NULL;
if ([[notification.userInfo objectForKey:@"id"] isKindOfClass:[NSString class]] ) {
notId = [notification.userInfo objectForKey:@"id"];
} else {
notId = [[notification.userInfo objectForKey:@"id"] stringValue];
}
if ([notId isEqualToString:id]) {
return notification;
}
}
return NULL;
}
/** /**
* Retrieves the application state * Retrieves the application state
* *
* @return {NSString} * @return
* Either "background" or "foreground" * Either "background" or "foreground"
*/ */
- (NSString*) applicationState - (NSString*) applicationState
...@@ -603,35 +445,8 @@ ...@@ -603,35 +445,8 @@
} }
/** /**
* Retrieves all scheduled notifications. * Simply invokes the callback without any parameter.
* */
* @return {NSArray}
* A list of all scheduled local notifications
*/
- (NSArray*) scheduledNotifications
{
NSMutableArray* notificationsWithoutNIL = [[NSMutableArray alloc]
init];
NSArray* notifications = [[UIApplication sharedApplication]
scheduledLocalNotifications];
for (UILocalNotification* notification in notifications)
{
if (notification) {
[notificationsWithoutNIL addObject:notification];
}
}
return notificationsWithoutNIL;
}
#pragma mark -
#pragma mark Plugin callback methods
/**
* Simply invokes the callback without any parameter.
*/
- (void) execCallback:(CDVInvokedUrlCommand*)command - (void) execCallback:(CDVInvokedUrlCommand*)command
{ {
CDVPluginResult *result = [CDVPluginResult CDVPluginResult *result = [CDVPluginResult
...@@ -642,26 +457,35 @@ ...@@ -642,26 +457,35 @@
} }
/** /**
* Fires the given event. * Fire general event.
*
* @param {NSString} event
* The Name of the event
* @param {NSString} id
* The ID of the notification
* @param {NSString} json
* A custom (JSON) string
*/ */
- (void) fireEvent:(NSString*)event id:(NSString*)id json:(NSString*)json - (void) fireEvent:(NSString*)event
{ {
NSString* appState = self.applicationState; [self fireEvent:event localNotification:NULL];
}
/**
* Fire event for local notification.
*/
- (void) fireEvent:(NSString*)event localNotification:(UILocalNotification*)notification
{
NSString* js;
NSString* params = [NSString stringWithFormat: NSString* params = [NSString stringWithFormat:
@"\"%@\",\"%@\",\\'%@\\'", @"\"%@\"", self.applicationState];
id, appState, json];
if (notification) {
NSString* id = notification.options.id;
NSString* json = notification.options.json;
NSString* args = [notification.options encodeToJSON];
params = [NSString stringWithFormat:
@"\"%@\",\"%@\",\\'%@\\',JSON.parse(\\'%@\\')",
id, self.applicationState, json, args];
}
NSString* js = [NSString stringWithFormat: js = [NSString stringWithFormat:
@"setTimeout('plugin.notification.local.on%@(%@)',0)", @"setTimeout('plugin.notification.local.on%@(%@)',0)",
event, params]; event, params];
if (deviceready) { if (deviceready) {
[self.commandDelegate evalJs:js]; [self.commandDelegate evalJs:js];
......
/*
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
@interface APPLocalNotificationOptions : NSObject
- (id) initWithDict:(NSDictionary*)dict;
@property (readonly, getter=id) NSString* id;
@property (readonly, getter=autoCancel) BOOL autoCancel;
@property (readonly, getter=json) NSString* json;
@property (readonly, getter=badgeNumber) NSInteger badgeNumber;
@property (readonly, getter=alertBody) NSString* alertBody;
@property (readonly, getter=soundName) NSString* soundName;
@property (readonly, getter=fireDate) NSDate* fireDate;
@property (readonly, getter=repeatInterval) NSCalendarUnit repeatInterval;
@property (readonly, getter=userInfo) NSDictionary* userInfo;
// Encode the user info dict to JSON
- (NSString*) encodeToJSON;
@end
/*
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
#import "APPLocalNotificationOptions.h"
#import <Cordova/CDVAvailability.h>
@interface APPLocalNotificationOptions ()
// The dictionary which contains all notification properties
@property(readwrite, assign) NSDictionary* dict;
@end
@implementation APPLocalNotificationOptions
@synthesize dict;
#pragma mark -
#pragma mark Initialization
/**
* Initialize the object with the given options when calling on JS side:
* notification.local.add(options)
*/
- (id) initWithDict:(NSDictionary*)dictionary
{
self = [super init];
self.dict = dictionary;
return self;
}
#pragma mark -
#pragma mark Attributes
/**
* The notification's ID.
*/
- (NSString*) id
{
return [dict objectForKey:@"id"];
}
/**
* The notification's title.
*/
- (NSString*) title
{
return [dict objectForKey:@"title"];
}
/**
* The notification's message.
*/
- (NSString*) message
{
return [dict objectForKey:@"message"];
}
/**
* The notification's auto cancel flag.
*/
- (BOOL) autoCancel
{
if (IsAtLeastiOSVersion(@"8.0")){
return YES;
} else {
return [[dict objectForKey:@"autoCancel"] boolValue];
}
}
/**
* The notification's JSON data.
*/
- (NSString*) json
{
return [dict objectForKey:@"json"];
}
/**
* The notification's badge number.
*/
- (NSInteger) badgeNumber
{
return [[dict objectForKey:@"badge"] intValue];
}
#pragma mark -
#pragma mark Complex Attributes
/**
* The notification's alert body.
*/
- (NSString*) alertBody
{
NSString* title = [self title];
NSString* msg = [self message];
NSString* alertBody = msg;
if (![self stringIsNullOrEmpty:title])
{
alertBody = [NSString stringWithFormat:@"%@\n%@",
title, msg];
}
return alertBody;
}
/**
* The notification's sound path.
*/
- (NSString*) soundName
{
NSString* path = [dict objectForKey:@"sound"];
if ([path hasPrefix:@"file:/"])
{
return [self soundNameForAsset:path];
}
else if ([path hasPrefix:@"res:"])
{
return [self soundNameForResource:path];
}
return UILocalNotificationDefaultSoundName;
}
/**
* The notification's fire date.
*/
- (NSDate*) fireDate
{
double timestamp = [[dict objectForKey:@"date"]
doubleValue];
return [NSDate dateWithTimeIntervalSince1970:timestamp];
}
/**
* The notification's repeat interval.
*/
- (NSCalendarUnit) repeatInterval
{
NSString* interval = [dict objectForKey:@"repeat"];
if ([interval isEqualToString:@"secondly"])
{
return NSCalendarUnitSecond;
}
else if ([interval isEqualToString:@"minutely"])
{
return NSCalendarUnitMinute;
}
else if ([interval isEqualToString:@"hourly"])
{
return NSCalendarUnitHour;
}
else if ([interval isEqualToString:@"daily"])
{
return NSCalendarUnitDay;
}
else if ([interval isEqualToString:@"weekly"])
{
return NSCalendarUnitWeekOfYear;
}
else if ([interval isEqualToString:@"monthly"])
{
return NSCalendarUnitMonth;
}
else if ([interval isEqualToString:@"yearly"])
{
return NSCalendarUnitYear;
}
return NSCalendarUnitEra;
}
/**
* The notification's user info dict.
*/
- (NSDictionary*) userInfo
{
return dict;
}
/**
* Encode the user info dict to JSON.
*/
- (NSString*) encodeToJSON
{
NSString* json;
NSData* data;
NSMutableDictionary* obj = [dict mutableCopy];
[obj removeObjectForKey:@"json"];
data = [NSJSONSerialization dataWithJSONObject:obj
options:NSJSONWritingPrettyPrinted
error:Nil];
json = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
return [json stringByReplacingOccurrencesOfString:@"\n"
withString:@""];
}
#pragma mark -
#pragma mark Helpers
/**
* Convert relative path to valid sound name attribute.
*/
- (NSString*) soundNameForAsset:(NSString*)path
{
return [path stringByReplacingOccurrencesOfString:@"file:/"
withString:@"www"];
}
/**
* Convert resource path to valid sound name attribute.
*/
- (NSString*) soundNameForResource:(NSString*)path
{
return [path pathComponents].lastObject;
}
/**
* If the string is empty.
*/
- (BOOL) stringIsNullOrEmpty:(NSString*)str
{
if (str == (NSString*)[NSNull null])
return YES;
if ([str isEqualToString:@""])
return YES;
return NO;
}
@end
/*
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
@interface UIApplication (APPLocalNotification)
@property (readonly, getter=triggeredLocalNotifications) NSArray* triggeredLocalNotifications;
@property (readonly, getter=triggeredLocalNotificationIds) NSArray* triggeredLocalNotificationIds;
@property (readonly, getter=scheduledLocalNotificationIds) NSArray* scheduledLocalNotificationIds;
// If the app has the permission to schedule local notifications
- (BOOL) hasPermissionToScheduleLocalNotifications;
// Ask for permission to schedule local notifications
- (void) registerPermissionToScheduleLocalNotifications;
// Get the scheduled local notification by ID
- (UILocalNotification*) scheduledLocalNotificationWithId:(NSString*)id;
// Get the triggered local notification by ID
- (UILocalNotification*) triggeredLocalNotificationWithId:(NSString*)id;
@end
/*
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
#import "UIApplication+APPLocalNotification.h"
#import "UILocalNotification+APPLocalNotification.h"
#import <Availability.h>
@implementation UIApplication (APPLocalNotification)
#pragma mark -
#pragma mark Permissions
/**
* If the app has the permission to schedule local notifications.
*/
- (BOOL) hasPermissionToScheduleLocalNotifications
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
UIUserNotificationType types;
UIUserNotificationSettings *settings;
settings = [[UIApplication sharedApplication]
currentUserNotificationSettings];
types = UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound;
return (settings.types & types);
#else
return YES;
#endif
}
/**
* Ask for permission to schedule local notifications.
*/
- (void) registerPermissionToScheduleLocalNotifications
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
UIUserNotificationType types;
UIUserNotificationSettings *settings;
types = UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound;
settings = [UIUserNotificationSettings settingsForTypes:types
categories:nil];
[[UIApplication sharedApplication]
registerUserNotificationSettings:settings];
#endif
}
#pragma mark -
#pragma mark LocalNotifications
/**
* List of all triggered local notifications which have been scheduled
* and not yet removed the notification center.
*/
- (NSArray*) triggeredLocalNotifications
{
NSArray* scheduledNotifications = self.scheduledLocalNotifications;
NSMutableArray* triggeredNotifications = [[NSMutableArray alloc] init];
for (UILocalNotification* notification in scheduledNotifications)
{
if (notification && [notification wasTriggered])
{
[triggeredNotifications addObject:notification];
}
}
return triggeredNotifications;
}
/**
* List of all triggered local notifications IDs which have been scheduled
* and not yet removed the notification center.
*/
- (NSArray*) triggeredLocalNotificationIds
{
NSArray* triggeredNotifications = self.triggeredLocalNotifications;
NSMutableArray* triggeredNotificationIds = [[NSMutableArray alloc] init];
for (UILocalNotification* notification in triggeredNotifications)
{
[triggeredNotificationIds addObject:notification.options.id];
}
return triggeredNotificationIds;
}
/**
* List of all scheduled local notifications IDs.
*/
- (NSArray*) scheduledLocalNotificationIds
{
NSArray* scheduledNotifications = self.scheduledLocalNotifications;
NSMutableArray* scheduledNotificationIds = [[NSMutableArray alloc] init];
for (UILocalNotification* notification in scheduledNotifications)
{
if (notification)
{
[scheduledNotificationIds addObject:notification.options.id];
}
}
return scheduledNotificationIds;
}
/**
* Get the scheduled local notification by ID.
*/
- (UILocalNotification*) scheduledLocalNotificationWithId:(NSString*)id
{
NSArray* notifications = self.scheduledLocalNotifications;
for (UILocalNotification* notification in notifications)
{
if (notification && [notification.options.id isEqualToString:id])
{
return notification;
}
}
return NULL;
}
/**
* Get the triggered local notification by ID.
*/
- (UILocalNotification*) triggeredLocalNotificationWithId:(NSString*)id
{
UILocalNotification* notification = [self scheduledLocalNotificationWithId:id];
if (notification && [notification wasTriggered]) {
return notification;
}
return NULL;
}
@end
/*
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
#import "APPLocalNotificationOptions.h"
@interface UILocalNotification (APPLocalNotification)
// Initialize a new local notification
- (id) initWithOptions:(NSDictionary*)dict;
// The options provided by the plug-in
- (APPLocalNotificationOptions*) options;
// Timeinterval since fire date
- (NSTimeInterval) timeIntervalSinceFireDate;
// If the fire date was in the past
- (BOOL) wasInThePast;
// If the notification was already triggered
- (BOOL) wasTriggered;
@end
/*
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
#import "UILocalNotification+APPLocalNotification.h"
#import "APPLocalNotificationOptions.h"
#import <objc/runtime.h>
static char optionsKey;
@implementation UILocalNotification (APPLocalNotification)
#pragma mark -
#pragma mark Init methods
/**
* Initialize a local notification with the given options when calling on JS side:
* notification.local.add(options)
*/
- (id) initWithOptions:(NSDictionary*)dict
{
self = [super init];
[self setUserInfo:dict];
[self __init];
return self;
}
/**
* Applies the given options when calling on JS side:
* notification.local.add(options)
*/
- (void) __init
{
APPLocalNotificationOptions* options = self.options;
self.fireDate = options.fireDate;
self.timeZone = [NSTimeZone defaultTimeZone];
self.applicationIconBadgeNumber = options.badgeNumber;
self.repeatInterval = options.repeatInterval;
self.alertBody = options.alertBody;
self.soundName = options.soundName;
}
/**
* The options provided by the plug-in.
*/
- (APPLocalNotificationOptions*) options
{
APPLocalNotificationOptions* options = [self getOptions];
if (!options) {
options = [[APPLocalNotificationOptions alloc]
initWithDict:[self userInfo]];
[self setOptions:options];
}
return options;
}
/**
* Get associated option object
*/
- (APPLocalNotificationOptions*) getOptions
{
return objc_getAssociatedObject(self, &optionsKey);
}
/**
* Set associated option object
*/
- (void) setOptions:(APPLocalNotificationOptions*)options
{
objc_setAssociatedObject(self, &optionsKey,
options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
/**
* Timeinterval since fire date.
*/
- (NSTimeInterval) timeIntervalSinceFireDate
{
NSDate* now = [NSDate date];
NSDate* fireDate = self.options.fireDate;
return [now timeIntervalSinceDate:fireDate];
}
/**
* If the fire date was in the past.
*/
- (BOOL) wasInThePast
{
return [self timeIntervalSinceFireDate] < 0;
}
/**
* If the notification was already triggered.
*/
- (BOOL) wasTriggered
{
NSDate* now = [NSDate date];
NSDate* fireDate = self.fireDate;
bool isLaterThanOrEqualTo = !([now compare:fireDate] == NSOrderedAscending);
return isLaterThanOrEqualTo;
}
@end
...@@ -19,338 +19,382 @@ ...@@ -19,338 +19,382 @@
under the License. under the License.
*/ */
var LocalNotification = function () { var exec = require('cordova/exec'),
this._defaults = {
message: '',
title: '',
autoCancel: false,
badge: 0,
id: '0',
json: '',
repeat: ''
};
};
LocalNotification.prototype = {
/**
* Returns the default settings
*
* @return {Object}
*/
getDefaults: function () {
return this._defaults;
},
/**
* Overwrite default settings
*
* @param {Object} defaults
*/
setDefaults: function (newDefaults) {
var defaults = this.getDefaults();
for (var key in defaults) {
if (newDefaults[key] !== undefined) {
defaults[key] = newDefaults[key];
}
}
},
/**
* @private
*
* Merges custom properties with the default values.
*
* @param {Object} options
* Set of custom values
*
* @retrun {Object}
* The merged property list
*/
mergeWithDefaults: function (options) {
var defaults = this.getDefaults();
for (var key in defaults) {
if (options[key] === undefined) {
options[key] = defaults[key];
}
}
return options;
},
/**
* @private
*
* Merges the platform specific properties into the default properties.
*
* @return {Object}
* The default properties for the platform
*/
applyPlatformSpecificOptions: function () {
var defaults = this._defaults;
switch (device.platform) {
case 'Android':
defaults.icon = 'icon';
defaults.smallIcon = null;
defaults.ongoing = false;
defaults.led = 'FFFFFF'; /*RRGGBB*/
defaults.sound = 'TYPE_NOTIFICATION'; break;
case 'iOS':
defaults.sound = ''; break;
case 'WinCE': case 'Win32NT':
defaults.smallImage = null;
defaults.image = null;
defaults.wideImage = null;
}
return defaults;
},
/**
* @private
*
* Creates a callback, which will be executed within a specific scope.
*
* @param {Function} callbackFn
* The callback function
* @param {Object} scope
* The scope for the function
*
* @return {Function}
* The new callback function
*/
createCallbackFn: function (callbackFn, scope) {
if (typeof callbackFn != 'function')
return;
return function () {
callbackFn.apply(scope || this, arguments);
};
},
/**
* Add a new entry to the registry
*
* @param {Object} options
* The notification properties
* @param {Function} callback
* A function to be called after the notification has been canceled
* @param {Object} scope
* The scope for the callback function
*
* @return {Number}
* The notification's ID
*/
add: function (options, callback, scope) {
var options = this.mergeWithDefaults(options),
callbackFn = this.createCallbackFn(callback, scope);
if (options.id) {
options.id = options.id.toString();
}
if (options.date === undefined) {
options.date = new Date();
}
if (options.title) {
options.title = options.title.toString();
}
if (options.message) {
options.message = options.message.toString();
}
if (typeof options.date == 'object') {
options.date = Math.round(options.date.getTime()/1000);
}
if (['WinCE', 'Win32NT'].indexOf(device.platform) > -1) {
callbackFn = function (cmd) {
eval(cmd);
};
}
cordova.exec(callbackFn, null, 'LocalNotification', 'add', [options]);
return options.id;
},
/**
* Cancels the specified notification.
*
* @param {String} id
* The ID of the notification
* @param {Function} callback
* A function to be called after the notification has been canceled
* @param {Object} scope
* The scope for the callback function
*/
cancel: function (id, callback, scope) {
var id = id.toString(),
callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'cancel', [id]);
},
/**
* Removes all previously registered notifications.
*
* @param {Function} callback
* A function to be called after all notifications have been canceled
* @param {Object} scope
* The scope for the callback function
*/
cancelAll: function (callback, scope) {
var callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'cancelAll', []);
},
/**
* Retrieves a list with all currently pending notifications.
*
* @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/
getScheduledIds: function (callback, scope) {
var callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'getScheduledIds', []);
},
/**
* Checks wether a notification with an ID is scheduled.
*
* @param {String} id
* The ID of the notification
* @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/
isScheduled: function (id, callback, scope) {
var id = id.toString(),
callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'isScheduled', [id]);
},
/**
* Retrieves a list with all triggered notifications.
*
* @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/
getTriggeredIds: function (callback, scope) {
var callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'getTriggeredIds', []);
},
/**
* Checks wether a notification with an ID was triggered.
*
* @param {String} id
* The ID of the notification
* @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/
isTriggered: function (id, callback, scope) {
var id = id.toString(),
callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'isTriggered', [id]);
},
/**
* Occurs when a notification was added.
*
* @param {String} id
* The ID of the notification
* @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/
onadd: function (id, state, json) {},
/**
* Occurs when the notification is triggered.
*
* @param {String} id
* The ID of the notification
* @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/
ontrigger: function (id, state, json) {},
/**
* Fires after the notification was clicked.
*
* @param {String} id
* The ID of the notification
* @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/
onclick: function (id, state, json) {},
/**
* Fires if the notification was canceled.
*
* @param {String} id
* The ID of the notification
* @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/
oncancel: function (id, state, json) {}
};
var plugin = new LocalNotification(),
channel = require('cordova/channel'); channel = require('cordova/channel');
// Called after all 'deviceready' listener are called
// Called after 'deviceready' event
channel.deviceready.subscribe( function () { channel.deviceready.subscribe( function () {
// Device is ready now, the listeners are registered and all queued events // Device is ready now, the listeners are registered
// can be executed now. // and all queued events can be executed.
cordova.exec(null, null, 'LocalNotification', 'deviceready', []); exec(null, null, 'LocalNotification', 'deviceready', []);
}); });
// Called before 'deviceready' event
channel.onCordovaReady.subscribe( function () { channel.onCordovaReady.subscribe( function () {
// The cordova device plugin is ready now // The cordova device plugin is ready now
channel.onCordovaInfoReady.subscribe( function () { channel.onCordovaInfoReady.subscribe( function () {
if (device.platform == 'Android') { if (device.platform == 'Android') {
channel.onPause.subscribe( function () { channel.onPause.subscribe( function () {
// Necessary to set the state to `background` // Necessary to set the state to `background`
cordova.exec(null, null, 'LocalNotification', 'pause', []); exec(null, null, 'LocalNotification', 'pause', []);
}); });
channel.onResume.subscribe( function () { channel.onResume.subscribe( function () {
// Necessary to set the state to `foreground` // Necessary to set the state to `foreground`
cordova.exec(null, null, 'LocalNotification', 'resume', []); exec(null, null, 'LocalNotification', 'resume', []);
}); });
// Necessary to set the state to `foreground` // Necessary to set the state to `foreground`
cordova.exec(null, null, 'LocalNotification', 'resume', []); exec(null, null, 'LocalNotification', 'resume', []);
} }
// Merges the platform specific properties into the default properties // Merges the platform specific properties into the default properties
plugin.applyPlatformSpecificOptions(); exports.applyPlatformSpecificOptions();
}); });
}); });
module.exports = plugin;
/**
* @private
*
* Default values.
*/
exports._defaults = {
message: '',
title: '',
autoCancel: false,
badge: 0,
id: '0',
json: '',
repeat: ''
};
/**
* Returns the default settings
*
* @return {Object}
*/
exports.getDefaults = function () {
return this._defaults;
};
/**
* Overwrite default settings
*
* @param {Object} defaults
*/
exports.setDefaults = function (newDefaults) {
var defaults = this.getDefaults();
for (var key in defaults) {
if (newDefaults[key] !== undefined) {
defaults[key] = newDefaults[key];
}
}
};
/**
* Add a new entry to the registry
*
* @param {Object} props
* The notification properties
* @param {Function} callback
* A function to be called after the notification has been canceled
* @param {Object} scope
* The scope for the callback function
*
* @return {Number}
* The notification's ID
*/
exports.add = function (props, callback, scope) {
var options = this.mergeWithDefaults(props),
fn = this.createCallbackFn(callback, scope);
if (options.id) {
options.id = options.id.toString();
}
if (options.date === undefined) {
options.date = new Date();
}
if (options.title) {
options.title = options.title.toString();
}
if (options.message) {
options.message = options.message.toString();
}
if (typeof options.date == 'object') {
options.date = Math.round(options.date.getTime()/1000);
}
if (typeof options.json == 'object') {
options.json = JSON.stringify(options.json);
}
if (['WinCE', 'Win32NT'].indexOf(device.platform) > -1) {
fn = function (cmd) {
eval(cmd);
};
}
exec(fn, null, 'LocalNotification', 'add', [options]);
return options.id;
};
/**
* Cancels the specified notification.
*
* @param {String} id
* The ID of the notification
* @param {Function} callback
* A function to be called after the notification has been canceled
* @param {Object} scope
* The scope for the callback function
*/
exports.cancel = function (id, callback, scope) {
var fn = this.createCallbackFn(callback, scope);
exec(fn, null, 'LocalNotification', 'cancel', [(id || '0').toString()]);
};
/**
* Removes all previously registered notifications.
*
* @param {Function} callback
* A function to be called after all notifications have been canceled
* @param {Object} scope
* The scope for the callback function
*/
exports.cancelAll = function (callback, scope) {
var fn = this.createCallbackFn(callback, scope);
exec(fn, null, 'LocalNotification', 'cancelAll', []);
};
/**
* Retrieves a list with all currently pending notifications.
*
* @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/
exports.getScheduledIds = function (callback, scope) {
var fn = this.createCallbackFn(callback, scope);
exec(fn, null, 'LocalNotification', 'getScheduledIds', []);
};
/**
* Checks wether a notification with an ID is scheduled.
*
* @param {String} id
* The ID of the notification
* @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/
exports.isScheduled = function (id, callback, scope) {
var fn = this.createCallbackFn(callback, scope);
exec(fn, null, 'LocalNotification', 'isScheduled', [id.toString()]);
};
/**
* Retrieves a list with all triggered notifications.
*
* @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/
exports.getTriggeredIds = function (callback, scope) {
var fn = this.createCallbackFn(callback, scope);
exec(fn, null, 'LocalNotification', 'getTriggeredIds', []);
};
/**
* Checks wether a notification with an ID was triggered.
*
* @param {String} id
* The ID of the notification
* @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/
exports.isTriggered = function (id, callback, scope) {
var fn = this.createCallbackFn(callback, scope);
exec(fn, null, 'LocalNotification', 'isTriggered', [id.toString()]);
};
/**
* Informs if the app has the permission to show notifications.
*
* @param {Function} callback
* The function to be exec as the callback
* @param {Object?} scope
* The callback function's scope
*/
exports.hasPermission = function (callback, scope) {
var fn = this.createCallbackFn(callback, scope);
if (device.platform != 'iOS') {
fn(true);
return;
}
exec(fn, null, 'LocalNotification', 'hasPermission', []);
};
/**
* Register permission to show notifications if not already granted.
*
* @param {Function} callback
* The function to be exec as the callback
* @param {Object?} scope
* The callback function's scope
*/
exports.registerPermission = function (callback, scope) {
if (device.platform != 'iOS')
return;
exec(null, null, 'LocalNotification', 'registerPermission', []);
};
exports.promptForPermission = function (callback, scope) {
console.warn('Depreated: Please use `notification.local.registerPermission` instead.');
exports.registerPermission.apply(this, arguments);
};
/**
* Occurs when a notification was added.
*
* @param {String} id
* The ID of the notification
* @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/
exports.onadd = function (id, state, json) {};
/**
* Occurs when the notification is triggered.
*
* @param {String} id
* The ID of the notification
* @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/
exports.ontrigger = function (id, state, json) {};
/**
* Fires after the notification was clicked.
*
* @param {String} id
* The ID of the notification
* @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/
exports.onclick = function (id, state, json) {};
/**
* Fires if the notification was canceled.
*
* @param {String} id
* The ID of the notification
* @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/
exports.oncancel = function (id, state, json) {};
/**
* @private
*
* Merges custom properties with the default values.
*
* @param {Object} options
* Set of custom values
*
* @retrun {Object}
* The merged property list
*/
exports.mergeWithDefaults = function (options) {
var defaults = this.getDefaults();
for (var key in defaults) {
if (options[key] === undefined) {
options[key] = defaults[key];
}
}
return options;
};
/**
* @private
*
* Merges the platform specific properties into the default properties.
*
* @return {Object}
* The default properties for the platform
*/
exports.applyPlatformSpecificOptions = function () {
var defaults = this._defaults;
switch (device.platform) {
case 'Android':
defaults.icon = 'icon';
defaults.smallIcon = null;
defaults.ongoing = false;
defaults.led = 'FFFFFF'; /*RRGGBB*/
defaults.sound = 'TYPE_NOTIFICATION'; break;
case 'iOS':
defaults.sound = ''; break;
case 'WinCE': case 'Win32NT':
defaults.smallImage = null;
defaults.image = null;
defaults.wideImage = null;
}
return defaults;
};
/**
* @private
*
* Creates a callback, which will be executed within a specific scope.
*
* @param {Function} callbackFn
* The callback function
* @param {Object} scope
* The scope for the function
*
* @return {Function}
* The new callback function
*/
exports.createCallbackFn = function (callbackFn, scope) {
if (typeof callbackFn != 'function')
return;
return function () {
callbackFn.apply(scope || this, arguments);
};
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment