Commit eb4f357d by Sebastián Katzer

Rewritten iOS

parent d5ac16c1
## ChangeLog
#### 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 `promptForPermission` to promt the user to grant permission 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:] Scope parameter for `isScheduled` and `getScheduledIds`
- [enhancement:] Callbacks for `add`, `cancel` & `cancelAll`
- [enhancement:] `image:` accepts remote URLs and local URIs (Android)
- [enhancement:] __iOS8 Support__
#### Version 0.7.4 (22.03.2014)
- [bugfix:] Platform specific properties were ignored.
......
......@@ -19,7 +19,7 @@ The purpose of the plugin is to create an platform independent javascript interf
## Supported Platforms
- **iOS**<br>
- **iOS** _(up to iOS8)_<br>
See [Local and Push Notification Programming Guide][ios_notification_guide] for detailed informations and screenshots.
- **Android** *(SDK >=7)*<br>
......@@ -71,14 +71,14 @@ More informations can be found [here][PGB_plugin].
## ChangeLog
#### 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 `promptForPermission` to promt the user to grant permission 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:] Scope parameter for `isScheduled` and `getScheduledIds`
- [enhancement:] Callbacks for `add`, `cancel` & `cancelAll`
- [enhancement:] `image:` accepts remote URLs and local URIs (Android)
- [enhancement:] __iOS8 Support__
#### Further informations
- See [CHANGELOG.md][changelog] to get the full changelog for the plugin.
......@@ -89,7 +89,7 @@ More informations can be found [here][PGB_plugin].
The plugin creates the object ```window.plugin.notification.local``` with the following methods:
1. [notification.local.hasPermission][has_permission]
2. [notification.local.promptForPermission][prompt_for_permission]
2. [notification.local.registerPermission][register_permission]
3. [notification.local.add][add]
4. [notification.local.cancel][cancel]
5. [notification.local.cancelAll][cancelall]
......@@ -125,15 +125,15 @@ window.plugin.notification.local.hasPermission(function (granted) {
});
```
### Prompt the user to grant permission for local notifications
The user can be prompted to grant the required permission through the `notification.local.promptForPermission` interface.
### 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.promptForPermission();
window.plugin.notification.local.registerPermission();
```
### Schedule local notifications
......@@ -563,7 +563,7 @@ This software is released under the [Apache 2.0 License][apache2_license].
[ontrigger]: #get-notified-when-a-local-notification-has-been-triggered
[platform-specific-properties]: #platform-specifics
[has_permission]: #determine-if-the-app-does-have-the-permission-to-show-local-notifications
[prompt_for_permission]: #prompt-the-user-to-grant-permission-for-local-notifications
[register_permission]: #register-permission-for-local-notifications
[add]: #schedule-local-notifications
[cancel]: #cancel-scheduled-local-notifications
[cancelall]: #cancel-all-scheduled-local-notifications
......
......@@ -35,6 +35,15 @@
<header-file src="src/ios/APPLocalNotification.h" />
<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>
<!-- android -->
......
......@@ -38,7 +38,7 @@
- (void) getScheduledIds:(CDVInvokedUrlCommand*)command;
// Informs if the app has the permission to show notifications
- (void) hasPermission:(CDVInvokedUrlCommand*)command;
// Ask for permission to show notifications
- (void) promptForPermission:(CDVInvokedUrlCommand*)command;
// Registers permission to show notifications
- (void) registerPermission:(CDVInvokedUrlCommand*)command;
@end
......@@ -20,12 +20,14 @@
*/
#import "APPLocalNotification.h"
#import "APPLocalNotificationOptions.h"
#import "UIApplication+APPLocalNotification.h"
#import "UILocalNotification+APPLocalNotification.h"
#import <Availability.h>
@interface APPLocalNotification ()
// Retrieves all scheduled notifications
@property (readonly, getter=scheduledNotifications) NSArray* scheduledNotifications;
// Retrieves the application state
@property (readonly, getter=applicationState) NSString* applicationState;
// All events will be queued until deviceready has been fired
......@@ -37,13 +39,13 @@
@implementation APPLocalNotification
@synthesize deviceready, eventQueue, applicationState, scheduledNotifications;
@synthesize deviceready, eventQueue;
#pragma mark -
#pragma mark Plugin interface methods
#pragma mark Interface
/**
* Executes all queued events.
* Execute all queued events.
*/
- (void) deviceready:(CDVInvokedUrlCommand*)command
{
......@@ -57,29 +59,24 @@
}
/**
* Schedules a new local notification.
* Schedule a new local notification.
*
* @param {NSMutableDictionary} properties
* The properties of the notification
* @param properties
* A dict of properties
*/
- (void) add:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
NSArray* arguments = [command arguments];
NSMutableDictionary* properties = [arguments objectAtIndex:0];
NSString* id = [properties objectForKey:@"id"];
NSDictionary* options = [[command arguments]
objectAtIndex:0];
if ([self isNotificationScheduledWithId:id]) {
UILocalNotification* notification = [self notificationWithId:id];
UILocalNotification* notification;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC),
dispatch_get_main_queue(), ^{
[self cancelNotification:notification fireEvent:NO];
});
}
notification = [[UILocalNotification alloc]
initWithOptions:options];
[self scheduleNotificationWithProperties:properties];
[self scheduleLocalNotification:notification];
[self fireEvent:@"add" localNotification:notification];
[self execCallback:command];
}];
}
......@@ -87,21 +84,22 @@
/**
* Cancels a given local notification.
*
* @param {NSString} id
* @param id
* The ID of the local notification
*/
- (void) cancel:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
NSArray* arguments = [command arguments];
NSString* id = [arguments objectAtIndex:0];
NSString* id = [[command arguments]
objectAtIndex:0];
UILocalNotification* notification = [self notificationWithId:id];
UILocalNotification* notification;
if (notification) {
[self cancelNotification:notification fireEvent:YES];
}
notification = [[UIApplication sharedApplication]
scheduledLocalNotificationWithId:id];
[self cancelLocalNotification:notification];
[self fireEvent:@"cancel" localNotification:notification];
[self execCallback:command];
}];
}
......@@ -112,37 +110,31 @@
- (void) cancelAll:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
NSArray* notifications = self.scheduledNotifications;
for (UILocalNotification* notification in notifications) {
[self cancelNotification:notification fireEvent:YES];
}
[[UIApplication sharedApplication]
cancelAllLocalNotifications];
[[UIApplication sharedApplication]
setApplicationIconBadgeNumber:0];
[self cancelAllLocalNotifications];
[self fireEvent:@"cancelall"];
[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
* @param callback
* The callback function to be called with the result
*/
- (void) isScheduled:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
NSArray* arguments = [command arguments];
NSString* id = [arguments objectAtIndex:0];
bool isScheduled = [self isNotificationScheduledWithId:id];
NSString* id = [[command arguments]
objectAtIndex:0];
CDVPluginResult* result;
UILocalNotification* notification;
notification = [[UIApplication sharedApplication]
scheduledLocalNotificationWithId:id];
bool isScheduled = notification != NULL;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:isScheduled];
......@@ -153,25 +145,16 @@
}
/**
* Retrieves a list of ids from all currently pending notifications.
*
* @param callback
* The callback function to be called with the result
* List of ids from all currently pending notifications.
*/
- (void) getScheduledIds:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
NSArray* notifications = self.scheduledNotifications;
NSMutableArray* scheduledIds = [[NSMutableArray alloc] init];
CDVPluginResult* result;
NSArray* scheduledIds;
for (UILocalNotification* notification in notifications)
{
NSString* id = [notification.userInfo objectForKey:@"id"];
[scheduledIds addObject:id];
}
scheduledIds = [[UIApplication sharedApplication]
scheduledLocalNotificationIds];
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:scheduledIds];
......@@ -184,18 +167,22 @@
/**
* Checks wether a notification with an ID was triggered.
*
* @param {NSString} id
* @param id
* The ID of the notification
* @param callback
* The callback function to be called with the result
*/
- (void) isTriggered:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
NSArray* arguments = [command arguments];
NSString* id = [arguments objectAtIndex:0];
bool isTriggered = [self isNotificationTriggeredWithId:id];
NSString* id = [[command arguments]
objectAtIndex:0];
CDVPluginResult* result;
UILocalNotification* notification;
notification = [[UIApplication sharedApplication]
triggeredLocalNotificationWithId:id];
bool isTriggered = notification != NULL;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:isTriggered];
......@@ -207,31 +194,18 @@
/**
* 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
{
[self.commandDelegate runInBackground:^{
NSArray* notifications = self.scheduledNotifications;
NSMutableArray* scheduledIds = [[NSMutableArray alloc] init];
CDVPluginResult* result;
NSArray* triggeredIds;
for (UILocalNotification* notification in notifications)
{
if (![self isNotificationTriggered:notification]) {
continue;
}
NSString* id = [notification.userInfo objectForKey:@"id"];
[scheduledIds addObject:id];
}
triggeredIds = [[UIApplication sharedApplication]
triggeredLocalNotificationIds];
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:scheduledIds];
messageAsArray:triggeredIds];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
......@@ -239,17 +213,17 @@
}
/**
* Informs if the app has the permission to show
* Inform if the app has the permission to show
* badges and local notifications.
*
* @param callback
* The function to be exec as the callback
*/
- (void) hasPermission:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
CDVPluginResult* result;
BOOL hasPermission = [self hasPermissionToSheduleNotifications];
BOOL hasPermission;
hasPermission = [[UIApplication sharedApplication]
hasPermissionToScheduleLocalNotifications];
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:hasPermission];
......@@ -261,174 +235,114 @@
/**
* Ask for permission to show badges.
*
* @param callback
* The function to be exec as the callback
*/
- (void) promptForPermission:(CDVInvokedUrlCommand *)command
- (void) registerPermission:(CDVInvokedUrlCommand *)command
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
UIUserNotificationType types;
UIUserNotificationSettings *settings;
types = UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound;
settings = [UIUserNotificationSettings settingsForTypes:types
categories:nil];
[self.commandDelegate runInBackground:^{
[[UIApplication sharedApplication]
registerUserNotificationSettings:settings];
registerPermissionToScheduleLocalNotifications];
}];
#endif
}
#pragma mark -
#pragma mark Plugin core methods
#pragma mark Core Logic
/**
* Schedules a new local notification and fies the coresponding event.
*
* @param {NSMutableDictionary} properties
* The properties of the notification
* Schedule the local notification.
*/
- (void) scheduleNotificationWithProperties:(NSMutableDictionary*)properties
- (void) scheduleLocalNotification:(UILocalNotification*)notification
{
UILocalNotification* notification = [self notificationWithProperties:
properties];
[self cancelForerunnerLocalNotification:notification];
NSDictionary* userInfo = notification.userInfo;
NSString* id = [userInfo objectForKey:@"id"];
NSString* json = [userInfo objectForKey:@"json"];
NSString* state = self.applicationState;
[self fireEvent:@"add" id:id json:json];
if ([state isEqualToString:@"background"]) {
[[UIApplication sharedApplication]
presentLocalNotificationNow:notification];
}
[[UIApplication sharedApplication]
scheduleLocalNotification:notification];
}
/**
* Cancels the given local notification
* and fires the cancel event.
*
* @param {NSString} id
* The ID of the local notification
* Cancel the local notification.
*/
- (void) cancelNotification:(UILocalNotification*)notification
fireEvent:(BOOL)fireEvent
- (void) cancelLocalNotification:(UILocalNotification*)notification
{
NSDictionary* userInfo = notification.userInfo;
NSString* id = [userInfo objectForKey:@"id"];
NSString* json = [userInfo objectForKey:@"json"];
if (!notification)
return;
if (notification==nil) {
NSLog(@"cancelNotification: Notification equals nil");
}else{
[[UIApplication sharedApplication]
cancelLocalNotification:notification];
}
if (fireEvent) {
[self fireEvent:@"cancel" id:id json:json];
}
}
/**
* Cancels all local notification with are older then
* a specific amount of seconds
*
* @param {float} seconds
* The time interval in seconds
* Cancel all currently scheduled notifications.
*/
- (void) cancelAllNotificationsWhichAreOlderThen:(float)seconds
- (void) cancelAllLocalNotifications
{
NSDate* now = [NSDate date];
NSArray* notifications = self.scheduledNotifications;
NSArray* notifications;
for (UILocalNotification* notification in notifications)
{
NSDate* fireDate = notification.fireDate;
NSTimeInterval fireDateDistance = [now timeIntervalSinceDate:
fireDate];
notifications = [[UIApplication sharedApplication]
scheduledLocalNotifications];
if (notification.repeatInterval == NSCalendarUnitEra
&& fireDateDistance > seconds) {
[self cancelNotification:notification fireEvent:YES];
}
for (UILocalNotification* notification in notifications) {
[self cancelLocalNotification:notification];
}
[[UIApplication sharedApplication]
cancelAllLocalNotifications];
[[UIApplication sharedApplication]
setApplicationIconBadgeNumber:0];
}
/**
* Creates an notification object based on the given properties.
*
* @param {NSMutableDictionary} properties
* The properties for the local notification
* @return {UILocalNotification}
* Cancel a maybe given forerunner with the same ID.
*/
- (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];
NSString* msg = [options objectForKey:@"message"];
NSString* title = [options objectForKey:@"title"];
NSString* sound = [options objectForKey:@"sound"];
NSString* repeat = [options objectForKey:@"repeat"];
NSInteger badge = [[options objectForKey:@"badge"] intValue];
forerunner = [[UIApplication sharedApplication]
scheduledLocalNotificationWithId:id];
notification.fireDate = [NSDate dateWithTimeIntervalSince1970:timestamp];
notification.timeZone = [NSTimeZone defaultTimeZone];
notification.userInfo = [self userDict:options];
notification.applicationIconBadgeNumber = badge;
if (!forerunner)
return;
notification.repeatInterval = [[[self repeatDict] objectForKey:repeat]
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])
{
if ([sound isEqualToString:@""]) {
notification.soundName = UILocalNotificationDefaultSoundName;
} else {
notification.soundName = sound;
}
}
return notification;
[self cancelLocalNotification:forerunner];
}
/**
* If the app has the permission to show badges.
* Cancels all local notification with are older then
* a specific amount of seconds
*
* @param {float} seconds
* The time interval in seconds
*/
- (BOOL) hasPermissionToSheduleNotifications
- (void) cancelAllNotificationsWhichAreOlderThen:(float)seconds
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
UIUserNotificationType types;
UIUserNotificationSettings *settings;
NSArray* notifications;
settings = [[UIApplication sharedApplication]
currentUserNotificationSettings];
types = UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound;
notifications = [[UIApplication sharedApplication]
scheduledLocalNotifications];
return (settings.types & types);
#else
return YES;
#endif
for (UILocalNotification* notification in notifications)
{
if (notification && notification.repeatInterval == NSCalendarUnitEra
&& notification.timeIntervalSinceFireDate > seconds)
{
[self cancelLocalNotification:notification];
[self fireEvent:@"cancel" localNotification:notification];
}
}
}
#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.
......@@ -436,37 +350,35 @@
*/
- (void) didReceiveLocalNotification:(NSNotification*)localNotification
{
UIApplication* app = [UIApplication sharedApplication];
UILocalNotification* notification = [localNotification object];
NSDictionary* userInfo = notification.userInfo;
NSString* id = [userInfo objectForKey:@"id"];
NSString* json = [userInfo objectForKey:@"json"];
BOOL autoCancel = [[userInfo objectForKey:@"autoCancel"] boolValue];
BOOL autoCancel = notification.options.autoCancel;
NSTimeInterval timeInterval = notification.timeIntervalSinceFireDate;
NSDate* now = [NSDate date];
NSDate* fireDate = notification.fireDate;
NSTimeInterval fireDateDistance = [now timeIntervalSinceDate:fireDate];
NSString* event = (fireDateDistance < 1) ? @"trigger" : @"click";
NSString* event = (timeInterval <= 1 && deviceready) ? @"trigger" : @"click";
if ([[self applicationState] isEqualToString:@"foreground"]) {
event = @"trigger";
}
app.applicationIconBadgeNumber -= 1;
[self fireEvent:event localNotification:notification];
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
{
NSDictionary* launchOptions = [notification userInfo];
UILocalNotification* localNotification = [launchOptions objectForKey:
UILocalNotification* localNotification;
localNotification = [launchOptions objectForKey:
UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotification) {
......@@ -476,6 +388,9 @@
}
}
#pragma mark -
#pragma mark Life Cycle
/**
* Registers obervers for the following events after plugin was initialized.
* didReceiveLocalNotification:
......@@ -483,7 +398,9 @@
*/
- (void) pluginInitialize
{
NSNotificationCenter* notificationCenter = [NSNotificationCenter
NSNotificationCenter* notificationCenter;
notificationCenter = [NSNotificationCenter
defaultCenter];
eventQueue = [[NSMutableArray alloc] init];
......@@ -509,153 +426,12 @@
}
#pragma mark -
#pragma mark Plugin helper methods
/**
* 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;
}
#pragma mark Helper
/**
* Retrieves the application state
*
* @return {NSString}
* @return
* Either "background" or "foreground"
*/
- (NSString*) applicationState
......@@ -669,33 +445,6 @@
}
/**
* Retrieves all scheduled notifications.
*
* @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
......@@ -708,24 +457,33 @@
}
/**
* Fires the given event.
*
* @param {NSString} event
* The Name of the event
* @param {NSString} id
* The ID of the notification
* @param {NSString} json
* A custom (JSON) string
* Fire general event.
*/
- (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:
@"\"%@\",\"%@\",\\'%@\\'",
id, appState, json];
@"\"%@\"", self.applicationState];
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)",
event, params];
......
/*
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
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