Commit fdf8470d by Sebastián Katzer

WIP enhanced iOS10 support

parent 30da4b36
......@@ -3,7 +3,7 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="de.appplant.cordova.plugin.local-notification"
version="0.8.4">
version="0.8.5-dev">
<name>LocalNotification</name>
......@@ -11,7 +11,7 @@
<repo>https://github.com/katzer/cordova-plugin-local-notifications.git</repo>
<keywords>appplant, notification, local notification</keywords>
<keywords>appplant, notification, local notification, user notification</keywords>
<license>Apache 2.0</license>
......@@ -20,23 +20,15 @@
<!-- cordova -->
<engines>
<engine name="cordova" version=">=3.6.0" />
<!-- TODO next version: Probably I meant cordova-lib -->
<!-- <engine name="cordova-plugman" version=">=4.3.0" /> -->
<engine name="cordova-plugman" version=">=4.3.0" />
<engine name="cordova-windows" version=">=4.2.0" />
<engine name="apple-ios" version=">=10.0.0" />
</engines>
<!-- dependencies -->
<dependency id="cordova-plugin-device" />
<dependency id="cordova-plugin-app-event" />
<!-- info -->
<info>
Your support is needed. If you use the local-notification plugin please support us in order to ensure further development.
https://github.com/katzer/cordova-plugin-local-notifications#supporting
Thank you!
</info>
<!-- js -->
<js-module src="www/local-notification.js" name="LocalNotification">
<clobbers target="cordova.plugins.notification.local" />
......@@ -63,17 +55,31 @@
</feature>
</config-file>
<framework src="UserNotifications.framework" />
<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" />
<header-file src="src/ios/UIApplication+APPLocalNotification.h" />
<source-file src="src/ios/UIApplication+APPLocalNotification.m" />
<header-file src="src/ios/UNUserNotificationCenter+APPLocalNotification.h" />
<source-file src="src/ios/UNUserNotificationCenter+APPLocalNotification.m" />
<header-file src="src/ios/UNMutableNotificationContent+APPLocalNotification.h" />
<source-file src="src/ios/UNMutableNotificationContent+APPLocalNotification.m" />
<header-file src="src/ios/UNNotificationRequest+APPLocalNotification.h" />
<source-file src="src/ios/UNNotificationRequest+APPLocalNotification.m" />
<header-file src="src/ios9/APPLocalNotificationOptions.ios9.h" />
<source-file src="src/ios9/APPLocalNotificationOptions.ios9.m" />
<header-file src="src/ios9/UIApplication+APPLocalNotification.ios9.h" />
<source-file src="src/ios9/UIApplication+APPLocalNotification.ios9.m" />
<header-file src="src/ios/UILocalNotification+APPLocalNotification.h" />
<source-file src="src/ios/UILocalNotification+APPLocalNotification.m" />
<header-file src="src/ios9/UILocalNotification+APPLocalNotification.ios9.h" />
<source-file src="src/ios9/UILocalNotification+APPLocalNotification.ios9.m" />
</platform>
......
......@@ -24,7 +24,9 @@
#import <Foundation/Foundation.h>
#import <Cordova/CDVPlugin.h>
@interface APPLocalNotification : CDVPlugin
@import UserNotifications;
@interface APPLocalNotification : CDVPlugin <UNUserNotificationCenterDelegate>
// Execute all queued events
- (void) deviceready:(CDVInvokedUrlCommand*)command;
......
......@@ -23,20 +23,28 @@
#import "APPLocalNotification.h"
#import "APPLocalNotificationOptions.h"
#import "UIApplication+APPLocalNotification.h"
#import "UILocalNotification+APPLocalNotification.h"
#import "UNUserNotificationCenter+APPLocalNotification.h"
#import "UNNotificationRequest+APPLocalNotification.h"
#import "UNMutableNotificationContent+APPLocalNotification.h"
@import UserNotifications;
#import "APPLocalNotificationOptions.ios9.h"
#import "UIApplication+APPLocalNotification.ios9.h"
#import "UILocalNotification+APPLocalNotification.ios9.h"
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
@interface APPLocalNotification ()
// Retrieves the application state
@property (readonly, getter=applicationState) NSString* applicationState;
// Property reader for [self app]
@property (readonly, getter=app) UIApplication* app;
// Property reader for [self center]
@property (readonly, getter=center) UNUserNotificationCenter* center;
// All events will be queued until deviceready has been fired
@property (readwrite, assign) BOOL deviceready;
// Event queue
@property (readonly, nonatomic, retain) NSMutableArray* eventQueue;
// Needed when calling `registerPermission`
// IOS9: TODO remove later
@property (nonatomic, retain) CDVInvokedUrlCommand* command;
@end
......@@ -73,24 +81,34 @@
NSArray* notifications = command.arguments;
[self.commandDelegate runInBackground:^{
for (NSDictionary* options in notifications) {
UILocalNotification* notification;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
for (NSDictionary* options in notifications) {
UNMutableNotificationContent* notification;
notification = [[UNMutableNotificationContent alloc]
initWithOptions:options];
notification = [[UILocalNotification alloc]
initWithOptions:options];
notification.timeZone = [NSTimeZone defaultTimeZone];
notification.repeatInterval = 0;
[self scheduleNotification:notification];
//[self fireEvent:@"add" notification:notification];
}
} else {
for (NSDictionary* options in notifications) {
UILocalNotification* notification;
[self scheduleLocalNotification:[notification copy]];
[self fireEvent:@"schedule" notification:notification];
notification = [[UILocalNotification alloc]
initWithOptions:options];
if (notifications.count > 1) {
[NSThread sleepForTimeInterval:0.01];
[self scheduleLocalNotification:[notification copy]];
[self fireEvent:@"schedule" localnotification:notification];
if (notifications.count > 1) {
[NSThread sleepForTimeInterval:0.01];
}
}
}
[self execCallback:command];
}];
}];
}
/**
......@@ -104,22 +122,43 @@
NSArray* notifications = command.arguments;
[self.commandDelegate runInBackground:^{
for (NSDictionary* options in notifications) {
NSNumber* id = [options objectForKey:@"id"];
UILocalNotification* notification;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
for (NSDictionary* options in notifications) {
NSNumber* id = [options objectForKey:@"id"];
UNNotificationRequest* notification;
notification = [self.center getNotificationWithId:id];
if (!notification)
continue;
// [self updateNotification:[notification copy]
// withOptions:options];
//
// [self fireEvent:@"update" notification:notification];
//
// if (notifications.count > 1) {
// [NSThread sleepForTimeInterval:0.01];
// }
}
} else {
for (NSDictionary* options in notifications) {
NSNumber* id = [options objectForKey:@"id"];
UILocalNotification* notification;
notification = [self.app localNotificationWithId:id];
notification = [self.app localNotificationWithId:id];
if (!notification)
continue;
if (!notification)
continue;
[self updateLocalNotification:[notification copy]
withOptions:options];
[self updateLocalNotification:[notification copy]
withOptions:options];
[self fireEvent:@"update" notification:notification];
[self fireEvent:@"update" localnotification:notification];
if (notifications.count > 1) {
[NSThread sleepForTimeInterval:0.01];
if (notifications.count > 1) {
[NSThread sleepForTimeInterval:0.01];
}
}
}
......@@ -136,16 +175,30 @@
- (void) cancel:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
for (NSNumber* id in command.arguments) {
UILocalNotification* notification;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
for (NSNumber* id in command.arguments) {
UNNotificationRequest* notification;
notification = [self.app localNotificationWithId:id];
notification = [self.center getNotificationWithId:id];
if (!notification)
continue;
if (!notification)
continue;
[self.app cancelLocalNotification:notification];
[self fireEvent:@"cancel" notification:notification];
[self.center cancelNotification:notification];
[self fireEvent:@"cancel" notification:notification];
}
} else {
for (NSNumber* id in command.arguments) {
UILocalNotification* notification;
notification = [self.app localNotificationWithId:id];
if (!notification)
continue;
[self.app cancelLocalNotification:notification];
[self fireEvent:@"cancel" localnotification:notification];
}
}
[self execCallback:command];
......@@ -158,7 +211,7 @@
- (void) cancelAll:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
[self cancelAllLocalNotifications];
[self cancelAllNotifications];
[self fireEvent:@"cancelall"];
[self execCallback:command];
}];
......@@ -173,16 +226,30 @@
- (void) clear:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
for (NSNumber* id in command.arguments) {
UILocalNotification* notification;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
for (NSNumber* id in command.arguments) {
UNNotificationRequest* notification;
notification = [self.center getNotificationWithId:id];
if (!notification)
continue;
notification = [self.app localNotificationWithId:id];
[self.center clearNotification:notification];
[self fireEvent:@"clear" notification:notification];
}
} else {
for (NSNumber* id in command.arguments) {
UILocalNotification* notification;
notification = [self.app localNotificationWithId:id];
if (!notification)
continue;
if (!notification)
continue;
[self.app clearLocalNotification:notification];
[self fireEvent:@"clear" notification:notification];
[self.app clearLocalNotification:notification];
[self fireEvent:@"clear" localnotification:notification];
}
}
[self execCallback:command];
......@@ -195,7 +262,7 @@
- (void) clearAll:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
[self clearAllLocalNotifications];
[self clearAllNotifications];
[self fireEvent:@"clearall"];
[self execCallback:command];
}];
......@@ -241,20 +308,23 @@
* The notification life cycle type
*/
- (void) isPresent:(CDVInvokedUrlCommand*)command
type:(APPLocalNotificationType)type;
type:(APPNotificationType)type;
{
[self.commandDelegate runInBackground:^{
NSNumber* id = [command argumentAtIndex:0];
BOOL exist;
CDVPluginResult* result;
if (type == NotifcationTypeAll) {
exist = [self.app localNotificationExist:id];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
exist = [self.center notificationExist:id type:type];
} else {
exist = [self.app localNotificationExist:id type:type];
if (type == NotifcationTypeAll) {
exist = [self.app localNotificationExist:id];
} else {
exist = [self.app localNotificationExist:id type:type];
}
}
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:exist];
......@@ -296,18 +366,22 @@
* The IDs of the notifications
*/
- (void) getIds:(CDVInvokedUrlCommand*)command
byType:(APPLocalNotificationType)type;
byType:(APPNotificationType)type;
{
[self.commandDelegate runInBackground:^{
CDVPluginResult* result;
NSArray* ids;
if (type == NotifcationTypeAll) {
ids = [self.app localNotificationIds];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
ids = [self.center getNotificationIdsByType:type];
} else {
ids = [self.app localNotificationIdsByType:type];
if (type == NotifcationTypeAll) {
ids = [self.app localNotificationIds];
} else {
ids = [self.app localNotificationIdsByType:type];
}
}
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:ids];
......@@ -380,21 +454,26 @@
* The ID of the notification
*/
- (void) getOption:(CDVInvokedUrlCommand*)command
byType:(APPLocalNotificationType)type;
byType:(APPNotificationType)type;
{
[self.commandDelegate runInBackground:^{
NSArray* ids = command.arguments;
NSArray* notifications;
CDVPluginResult* result;
if (type == NotifcationTypeAll) {
notifications = [self.app localNotificationOptionsById:ids];
}
else {
notifications = [self.app localNotificationOptionsByType:type
andId:ids];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
notifications = [self.center getNotificationOptionsByType:type
andId:ids];
} else {
if (type == NotifcationTypeAll) {
notifications = [self.app localNotificationOptionsById:ids];
}
else {
notifications = [self.app localNotificationOptionsByType:type
andId:ids];
}
}
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:[notifications firstObject]];
......@@ -412,27 +491,43 @@
* The IDs of the notifications
*/
- (void) getOptions:(CDVInvokedUrlCommand*)command
byType:(APPLocalNotificationType)type;
byType:(APPNotificationType)type;
{
[self.commandDelegate runInBackground:^{
NSArray* ids = command.arguments;
NSArray* notifications;
CDVPluginResult* result;
if (type == NotifcationTypeAll && ids.count == 0) {
notifications = [self.app localNotificationOptions];
}
else if (type == NotifcationTypeAll) {
notifications = [self.app localNotificationOptionsById:ids];
}
else if (ids.count == 0) {
notifications = [self.app localNotificationOptionsByType:type];
}
else {
notifications = [self.app localNotificationOptionsByType:type
andId:ids];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
if (type == NotifcationTypeAll && ids.count == 0) {
notifications = [self.center getNotificationOptions];
}
else if (type == NotifcationTypeAll) {
notifications = [self.center getNotificationOptionsById:ids];
}
else if (ids.count == 0) {
notifications = [self.center getNotificationOptionsByType:type];
}
else {
notifications = [self.center getNotificationOptionsByType:type
andId:ids];
}
} else {
if (type == NotifcationTypeAll && ids.count == 0) {
notifications = [self.app localNotificationOptions];
}
else if (type == NotifcationTypeAll) {
notifications = [self.app localNotificationOptionsById:ids];
}
else if (ids.count == 0) {
notifications = [self.app localNotificationOptionsByType:type];
}
else {
notifications = [self.app localNotificationOptionsByType:type
andId:ids];
}
}
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:notifications];
......@@ -447,18 +542,35 @@
*/
- (void) hasPermission:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
CDVPluginResult* result;
BOOL hasPermission;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
[self.commandDelegate runInBackground:^{
[self.center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings* settings) {
BOOL authorized = settings.authorizationStatus == UNAuthorizationStatusAuthorized;
BOOL enabled = settings.notificationCenterSetting == UNNotificationSettingEnabled;
BOOL permitted = authorized && enabled;
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:permitted];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}];
} else {
[self.commandDelegate runInBackground:^{
CDVPluginResult* result;
BOOL hasPermission;
hasPermission = [self.app hasPermissionToScheduleLocalNotifications];
hasPermission = [self.app hasPermissionToScheduleLocalNotifications];
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:hasPermission];
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:hasPermission];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
}
/**
......@@ -466,16 +578,27 @@
*/
- (void) registerPermission:(CDVInvokedUrlCommand*)command
{
if ([[UIApplication sharedApplication]
respondsToSelector:@selector(registerUserNotificationSettings:)])
{
_command = command;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
[self.commandDelegate runInBackground:^{
[self.app registerPermissionToScheduleLocalNotifications];
UNAuthorizationOptions options =
(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert);
[self.center requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError* e) {
[self hasPermission:command];
}];
}];
} else {
[self hasPermission:command];
if ([[UIApplication sharedApplication]
respondsToSelector:@selector(registerUserNotificationSettings:)])
{
_command = command;
[self.commandDelegate runInBackground:^{
[self.app registerPermissionToScheduleLocalNotifications];
}];
} else {
[self hasPermission:command];
}
}
}
......@@ -485,47 +608,219 @@
/**
* Schedule the local notification.
*/
- (void) scheduleLocalNotification:(UILocalNotification*)notification
- (void) scheduleNotification:(UNMutableNotificationContent*)notification
{
[self cancelForerunnerLocalNotification:notification];
[self.app scheduleLocalNotification:notification];
[self.center addNotificationRequest:notification.request
withCompletionHandler:^(NSError* e) {
[self fireEvent:@"add" notification:notification.request];
}];
}
/**
* Update the local notification.
*/
- (void) updateLocalNotification:(UILocalNotification*)notification
withOptions:(NSDictionary*)newOptions
- (void) updateNotification:(UILocalNotification*)notification
withOptions:(NSDictionary*)newOptions
{
NSMutableDictionary* options = [notification.userInfo mutableCopy];
[options addEntriesFromDictionary:newOptions];
[options setObject:[NSDate date] forKey:@"updatedAt"];
notification = [[UILocalNotification alloc]
initWithOptions:options];
[self scheduleLocalNotification:notification];
// notification = [[UILocalNotification alloc]
// initWithOptions:options];
//
// [self scheduleLocalNotification:notification];
}
/**
* Cancel all local notifications.
*/
- (void) cancelAllLocalNotifications
- (void) cancelAllNotifications
{
[self.app cancelAllLocalNotifications];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
[self.center cancelAllNotifications];
} else {
[self.app cancelAllLocalNotifications];
}
[self.app setApplicationIconBadgeNumber:0];
}
/**
* Clear all local notifications.
*/
- (void) clearAllLocalNotifications
- (void) clearAllNotifications
{
[self.app clearAllLocalNotifications];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
[self.center clearAllNotifications];
} else {
[self.app clearAllLocalNotifications];
}
[self.app setApplicationIconBadgeNumber:0];
}
#pragma mark -
#pragma mark Delegates
/**
* Called when a notification is delivered to a foreground app.
*/
- (void) userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
{
[self fireEvent:@"trigger" notification:notification.request];
completionHandler(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert);
}
/**
* Called to let your app know which action was selected by the user for a given
* notification.
*/
- (void) userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler
{
UNNotificationRequest* notification = response.notification.request;
[self fireEvent:@"click" notification:notification];
if ([notification.options isRepeating]) {
[self.center clearNotification:notification];
[self fireEvent:@"clear" notification:notification];
} else {
[self.center cancelNotification:notification];
[self fireEvent:@"cancel" notification:notification];
}
completionHandler();
}
#pragma mark -
#pragma mark Life Cycle
/**
* Registers obervers after plugin was initialized.
*/
- (void) pluginInitialize
{
eventQueue = [[NSMutableArray alloc] init];
self.center.delegate = self;
}
#pragma mark -
#pragma mark Helper
/**
* Retrieves the application state
*
* @return
* Either "background" or "foreground"
*/
- (NSString*) applicationState
{
UIApplicationState state = [self.app applicationState];
bool isActive = state == UIApplicationStateActive;
return isActive ? @"foreground" : @"background";
}
/**
* Simply invokes the callback without any parameter.
*/
- (void) execCallback:(CDVInvokedUrlCommand*)command
{
CDVPluginResult *result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}
/**
* Short hand for shared application instance.
*/
- (UIApplication*) app
{
return [UIApplication sharedApplication];
}
/**
* Short hand for current notification center.
*/
- (UNUserNotificationCenter*) center
{
return [UNUserNotificationCenter currentNotificationCenter];
}
/**
* Fire general event.
*/
- (void) fireEvent:(NSString*)event
{
[self fireEvent:event notification:NULL];
}
/**
* Fire event for local notification.
*/
- (void) fireEvent:(NSString*)event
notification:(UNNotificationRequest*)notification
{
NSString* js;
NSString* appState = [self applicationState];
NSString* params = [NSString stringWithFormat:@"\"%@\"", appState];
if (notification) {
NSString* args = [notification encodeToJSON];
params = [NSString stringWithFormat:@"%@,'%@'", args, appState];
}
js = [NSString stringWithFormat:
@"cordova.plugins.notification.local.core.fireEvent('%@', %@)",
event, params];
if (deviceready) {
[self.commandDelegate evalJs:js];
} else {
[self.eventQueue addObject:js];
}
}
#pragma mark -
#pragma mark ios 9
/**
* Schedule the local notification.
*/
- (void) scheduleLocalNotification:(UILocalNotification*)notification
{
[self cancelForerunnerLocalNotification:notification];
[self.app scheduleLocalNotification:notification];
}
/**
* Update the local notification.
*/
- (void) updateLocalNotification:(UILocalNotification*)notification
withOptions:(NSDictionary*)newOptions
{
NSMutableDictionary* options = [notification.userInfo mutableCopy];
[options addEntriesFromDictionary:newOptions];
[options setObject:[NSDate date] forKey:@"updatedAt"];
notification = [[UILocalNotification alloc]
initWithOptions:options];
[self scheduleLocalNotification:notification];
}
/**
* Cancel a maybe given forerunner with the same ID.
*/
......@@ -558,14 +853,11 @@
&& notification.timeIntervalSinceFireDate > seconds)
{
[self.app cancelLocalNotification:notification];
[self fireEvent:@"cancel" notification:notification];
[self fireEvent:@"cancel" localnotification:notification];
}
}
}
#pragma mark -
#pragma mark Delegates
/**
* Calls the cancel or trigger event after a local notification was received.
* Cancels the local notification if autoCancel was set to true.
......@@ -580,16 +872,16 @@
NSTimeInterval timeInterval = [notification timeIntervalSinceLastTrigger];
NSString* event = timeInterval < 0.2 && deviceready ? @"trigger" : @"click";
[self fireEvent:event notification:notification];
[self fireEvent:event localnotification:notification];
if (![event isEqualToString:@"click"])
return;
if ([notification isRepeating]) {
[self fireEvent:@"clear" notification:notification];
[self fireEvent:@"clear" localnotification:notification];
} else {
[self.app cancelLocalNotification:notification];
[self fireEvent:@"cancel" notification:notification];
[self fireEvent:@"cancel" localnotification:notification];
}
}
......@@ -624,17 +916,6 @@
}
}
#pragma mark -
#pragma mark Life Cycle
/**
* Registers obervers after plugin was initialized.
*/
- (void) pluginInitialize
{
eventQueue = [[NSMutableArray alloc] init];
}
/**
* Clears all single repeating notifications which are older then 5 days
* before the app terminates.
......@@ -644,98 +925,11 @@
[self cancelAllNotificationsWhichAreOlderThen:432000];
}
#pragma mark -
#pragma mark Helper
/**
* Retrieves the application state
*
* @return
* Either "background" or "foreground"
*/
- (NSString*) applicationState
{
UIApplicationState state = [self.app applicationState];
bool isActive = state == UIApplicationStateActive;
return isActive ? @"foreground" : @"background";
}
/**
* Simply invokes the callback without any parameter.
*/
- (void) execCallback:(CDVInvokedUrlCommand*)command
{
CDVPluginResult *result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}
/**
* Short hand for shared application instance.
*/
- (UIApplication*) app
{
return [UIApplication sharedApplication];
}
/**
* Fire general event.
*/
- (void) fireEvent:(NSString*)event
{
[self fireEvent:event notification:NULL];
}
/**
* Fire event for local notification.
*/
- (void) fireEvent:(NSString*)event notification:(UILocalNotification*)notification
- (void) fireEvent:(NSString*)event localnotification:(UILocalNotification*)notification
{
if (IsAtLeastiOSVersion(@"10.0")) {
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:notification.alertTitle arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:notification.alertBody
arguments:nil];
content.sound = [UNNotificationSound defaultSound];
NSDate *fireDate = notification.fireDate;
if(fireDate==nil) {
fireDate = [NSDate date];
}
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
// Extract all date components into dateComponents
NSDateComponents *dateComponents = [gregorianCalendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
| NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit
fromDate:fireDate];
[dateComponents setTimeZone:[NSTimeZone defaultTimeZone]];
/// 4. update application icon badge number
//content.badge = @([[UIApplication sharedApplication] applicationIconBadgeNumber] + 1);
// Deliver the notification at the fire date.
UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:dateComponents repeats:NO];
NSString *identifier = @"DefaultNotificationIdentifier";
if(notification.userInfo!=nil && [notification.userInfo objectForKey:@"id"]!=nil) {
identifier = [notification.userInfo objectForKey:@"id"];
}
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];
/// 3. schedule localNotification
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(@"add NotificationRequest succeeded!");
}
}];
}
NSString* js;
NSString* params = [NSString stringWithFormat:
@"\"%@\"", self.applicationState];
......
......@@ -20,7 +20,9 @@
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import <UserNotifications/UNNotificationSound.h>
#import <UserNotifications/UNNotificationRequest.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
......@@ -29,14 +31,17 @@
- (id) initWithDict:(NSDictionary*)dict;
@property (readonly, getter=id) NSNumber* id;
@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=identifier) NSString* identifier;
@property (readonly, getter=title) NSString* title;
@property (readonly, getter=subtitle) NSString* subtitle;
@property (readonly, getter=badge) NSNumber* badge;
@property (readonly, getter=text) NSString* text;
@property (readonly, getter=sound) UNNotificationSound* sound;
@property (readonly, getter=userInfo) NSDictionary* userInfo;
// If it's a repeating notification
- (BOOL) isRepeating;
// how and when to trigger the notification
- (UNNotificationTrigger*) trigger;
@end
......@@ -23,8 +23,7 @@
#import "APPLocalNotificationOptions.h"
// Default sound ressource path
NSString* const DEFAULT_SOUND = @"res://platform_default";
@import UserNotifications;
@interface APPLocalNotificationOptions ()
......@@ -67,6 +66,14 @@ NSString* const DEFAULT_SOUND = @"res://platform_default";
}
/**
* The notification's ID as a string.
*/
- (NSString*) identifier
{
return [NSString stringWithFormat:@"%@", self.id];
}
/**
* The notification's title.
*/
- (NSString*) title
......@@ -75,63 +82,53 @@ NSString* const DEFAULT_SOUND = @"res://platform_default";
}
/**
* The notification's message.
* The notification's title.
*/
- (NSString*) text
- (NSString*) subtitle
{
return [dict objectForKey:@"text"];
NSArray *parts = [self.title componentsSeparatedByString:@"\n"];
return parts.count < 2 ? @"" : [parts objectAtIndex:1];
}
/**
* The notification's badge number.
* The notification's message.
*/
- (NSInteger) badgeNumber
- (NSString*) text
{
return [[dict objectForKey:@"badge"] intValue];
return [dict objectForKey:@"text"];
}
#pragma mark -
#pragma mark Complex Attributes
/**
* The notification's alert body.
* The notification's badge number.
*/
- (NSString*) alertBody
- (NSNumber*) badge
{
NSString* title = [self title];
NSString* msg = [self text];
NSString* alertBody = msg;
if (![self stringIsNullOrEmpty:title])
{
alertBody = [NSString stringWithFormat:@"%@\n%@",
title, msg];
}
return alertBody;
return [NSNumber numberWithInt:[[dict objectForKey:@"badge"] intValue]];
}
/**
* The notification's sound path.
*/
- (NSString*) soundName
- (UNNotificationSound*) sound
{
NSString* path = [dict objectForKey:@"sound"];
NSString* file;
if ([self stringIsNullOrEmpty:path])
return NULL;
if ([path isEqualToString:DEFAULT_SOUND])
return UILocalNotificationDefaultSoundName;
if ([path isEqualToString:@"res://platform_default"])
return [UNNotificationSound defaultSound];
if ([path hasPrefix:@"file:/"])
return [self soundNameForAsset:path];
if ([path hasPrefix:@"res:"])
return [self soundNameForResource:path];
if ([path hasPrefix:@"file:/"]) {
file = [self soundNameForAsset:path];
} else
if ([path hasPrefix:@"res:"]) {
file = [self soundNameForResource:path];
}
return NULL;
return [UNNotificationSound soundNamed:file];
}
/**
......@@ -146,47 +143,27 @@ NSString* const DEFAULT_SOUND = @"res://platform_default";
}
/**
* The notification's repeat interval.
* If it's a repeating notification.
*/
- (NSCalendarUnit) repeatInterval
- (BOOL) isRepeating
{
NSString* interval = [dict objectForKey:@"every"];
if ([self stringIsNullOrEmpty:interval]) {
return NSCalendarUnitEra;
}
else if ([interval isEqualToString:@"second"]) {
return NSCalendarUnitSecond;
}
else if ([interval isEqualToString:@"minute"]) {
return NSCalendarUnitMinute;
}
else if ([interval isEqualToString:@"hour"]) {
return NSCalendarUnitHour;
}
else if ([interval isEqualToString:@"day"]) {
return NSCalendarUnitDay;
}
else if ([interval isEqualToString:@"week"]) {
return NSCalendarUnitWeekOfYear;
}
else if ([interval isEqualToString:@"month"]) {
return NSCalendarUnitMonth;
}
else if ([interval isEqualToString:@"quarter"]) {
return NSCalendarUnitQuarter;
}
else if ([interval isEqualToString:@"year"]) {
return NSCalendarUnitYear;
}
return NSCalendarUnitEra;
return ![self stringIsNullOrEmpty:interval];
}
#pragma mark -
#pragma mark Methods
/**
* Specify how and when to trigger the notification.
*/
- (UNNotificationTrigger*) trigger
{
return [self isRepeating] ? [self triggerWithDateMatchingComponents] : [self triggerWithTimeInterval];
}
/**
* The notification's user info dict.
*/
- (NSDictionary*) userInfo
......@@ -202,18 +179,79 @@ NSString* const DEFAULT_SOUND = @"res://platform_default";
return dict;
}
#pragma mark -
#pragma mark Private
/**
* If it's a repeating notification.
* Returns a trigger based on a custom time interval in seconds.
*/
- (BOOL) isRepeating
- (UNTimeIntervalNotificationTrigger*) triggerWithTimeInterval
{
NSCalendarUnit interval = self.repeatInterval;
return [UNTimeIntervalNotificationTrigger
triggerWithTimeInterval:[self timeInterval] repeats:NO];
}
/**
* Returns a trigger based on a calendar time.
*/
- (UNCalendarNotificationTrigger*) triggerWithDateMatchingComponents
{
NSCalendar* cal = [[NSCalendar alloc]
initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *date = [cal components:[self repeatInterval]
fromDate:[self fireDate]];
return !(interval == NSCalendarUnitEra || interval == 0);
[date setTimeZone:[NSTimeZone defaultTimeZone]];
return [UNCalendarNotificationTrigger
triggerWithDateMatchingComponents:date repeats:YES];
}
#pragma mark -
#pragma mark Helpers
/**
* Timeinterval between future fire date and now.
*/
- (double) timeInterval
{
return MAX(0.01f, [self.fireDate timeIntervalSinceDate:[NSDate date]]);
}
/**
* The notification's repeat interval.
*/
- (NSCalendarUnit) repeatInterval
{
NSString* interval = [dict objectForKey:@"every"];
NSCalendarUnit unitFlags = NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
if ([self stringIsNullOrEmpty:interval]) {
return unitFlags;
}
else if ([interval isEqualToString:@"second"]) {
return NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay;
}
else if ([interval isEqualToString:@"minute"]) {
return NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitSecond;
}
else if ([interval isEqualToString:@"hour"]) {
return NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitMinute;
}
else if ([interval isEqualToString:@"day"]) {
return NSCalendarUnitHour|NSCalendarUnitMinute;
}
else if ([interval isEqualToString:@"week"]) {
return NSCalendarUnitWeekday|NSCalendarUnitHour|NSCalendarUnitMinute;
}
else if ([interval isEqualToString:@"month"]) {
return NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute;
}
else if ([interval isEqualToString:@"year"]) {
return NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute;
}
return unitFlags;
}
/**
* Convert relative path to valid sound name attribute.
......@@ -237,13 +275,7 @@ NSString* const DEFAULT_SOUND = @"res://platform_default";
*/
- (BOOL) stringIsNullOrEmpty:(NSString*)str
{
if (str == (NSString*)[NSNull null])
return YES;
if ([str isEqualToString:@""])
return YES;
return NO;
return (!str.length);
}
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "APPLocalNotificationOptions.h"
@import UserNotifications;
@interface UNMutableNotificationContent (APPLocalNotification)
// Initialize a new local notification
- (id) initWithOptions:(NSDictionary*)dict;
// The options provided by the plug-in
- (APPLocalNotificationOptions*) options;
// Fully configured request to add the notification to the notification center
- (UNNotificationRequest*) request;
// Encode the user info dict to JSON
- (NSString*) encodeToJSON;
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "UNMutableNotificationContent+APPLocalNotification.h"
#import "APPLocalNotificationOptions.h"
#import <objc/runtime.h>
@import UserNotifications;
static char optionsKey;
@implementation UNMutableNotificationContent (APPLocalNotification)
#pragma mark -
#pragma mark Init
/**
* Initialize a local notification with the given options when calling on JS side:
* notification.local.add(options)
*/
- (id) initWithOptions:(NSDictionary*)dict
{
self = [self 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.title = options.title;
self.subtitle = options.subtitle;
self.body = options.text;
self.sound = options.sound;
self.badge = options.badge;
}
#pragma mark -
#pragma mark Methods
/**
* 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);
}
/**
* The notifcations request ready to add to the notification center including
* all informations about trigger behavior.
*/
- (UNNotificationRequest*) request
{
APPLocalNotificationOptions* opts = [self getOptions];
return [UNNotificationRequest requestWithIdentifier:opts.identifier
content:self
trigger:opts.trigger];
}
/**
* Encode the user info dict to JSON.
*/
- (NSString*) encodeToJSON
{
NSString* json;
NSData* data;
NSMutableDictionary* obj = [self.userInfo mutableCopy];
[obj removeObjectForKey:@"updatedAt"];
if (obj == NULL || obj.count == 0)
return json;
data = [NSJSONSerialization dataWithJSONObject:obj
options:NSJSONWritingPrettyPrinted
error:NULL];
json = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
return [json stringByReplacingOccurrencesOfString:@"\n"
withString:@""];
}
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
@import UserNotifications;
@interface UNNotificationRequest (APPLocalNotification)
// The options provided by the plug-in
- (APPLocalNotificationOptions*) options;
// Encode the user info dict to JSON
- (NSString*) encodeToJSON;
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "UNMutableNotificationContent+APPLocalNotification.h"
#import "APPLocalNotificationOptions.h"
#import "UNNotificationRequest+APPLocalNotification.h"
#import <objc/runtime.h>
@import UserNotifications;
static char optionsKey;
@implementation UNNotificationRequest (APPLocalNotification)
/**
* 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);
}
/**
* The options provided by the plug-in.
*/
- (APPLocalNotificationOptions*) options
{
APPLocalNotificationOptions* options = [self getOptions];
if (!options) {
options = [[APPLocalNotificationOptions alloc]
initWithDict:[self.content userInfo]];
[self setOptions:options];
}
return options;
}
/**
* Encode the user info dict to JSON.
*/
- (NSString*) encodeToJSON
{
NSString* json;
NSData* data;
NSMutableDictionary* obj = [self.content.userInfo mutableCopy];
[obj removeObjectForKey:@"updatedAt"];
if (obj == NULL || obj.count == 0)
return json;
data = [NSJSONSerialization dataWithJSONObject:obj
options:NSJSONWritingPrettyPrinted
error:NULL];
json = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
return [json stringByReplacingOccurrencesOfString:@"\n"
withString:@""];
}
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "UNMutableNotificationContent+APPLocalNotification.h"
@interface UNUserNotificationCenter (APPLocalNotification)
typedef NS_ENUM(NSUInteger, APPNotificationType) {
NotifcationTypeAll = 0,
NotifcationTypeScheduled = 1,
NotifcationTypeTriggered = 2
};
#define APPNotificationType_DEFINED
@property (readonly, getter=getNotifications) NSArray* localNotifications;
@property (readonly, getter=getNotificationIds) NSArray* localNotificationIds;
// List of all notification IDs from given type
- (NSArray*) getNotificationIdsByType:(APPNotificationType)type;
// Find out if notification with ID exists
- (BOOL) notificationExist:(NSNumber*)id;
// Find out if notification with ID and type exists
- (BOOL) notificationExist:(NSNumber*)id type:(APPNotificationType)type;
// Find notification by ID
- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id;
// Find notification by ID and type
- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id andType:(APPNotificationType)type;
// Property list from all local notifications
- (NSArray*) getNotificationOptions;
// Property list from given local notifications
- (NSArray*) getNotificationOptionsById:(NSArray*)ids;
// Property list from all local notifications with type constraint
- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type;
// Property list from given local notifications with type constraint
- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type andId:(NSArray*)ids;
// Clear specified notfication
- (void) clearNotification:(UNNotificationRequest*)notification;
// Clear all notfications
- (void) clearAllNotifications;
// Cancel specified notfication
- (void) cancelNotification:(UNNotificationRequest*)notification;
// Cancel all notfications
- (void) cancelAllNotifications;
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "UNUserNotificationCenter+APPLocalNotification.h"
#import "UNNotificationRequest+APPLocalNotification.h"
@import UserNotifications;
@implementation UNUserNotificationCenter (APPLocalNotification)
#pragma mark -
#pragma mark LocalNotifications
/**
* List of all delivered or still pending notifications.
*/
- (NSArray*) getNotifications
{
NSMutableArray* notifications = [[NSMutableArray alloc] init];
[notifications addObjectsFromArray:[self getPendingNotifications]];
[notifications addObjectsFromArray:[self getDeliveredNotifications]];
return notifications;
}
/**
* List of all triggered notifications.
*/
- (NSArray*) getDeliveredNotifications
{
NSMutableArray* notifications = [[NSMutableArray alloc] init];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> *delivered) {
for (UNNotification* notification in delivered) {
[notifications addObject:notification.request];
}
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return notifications;
}
/**
* List of all pending notifications.
*/
- (NSArray*) getPendingNotifications
{
NSMutableArray* notifications = [[NSMutableArray alloc] init];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> *requests) {
[notifications addObjectsFromArray:requests];
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return notifications;
}
/**
* List of all notifications from given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) getNotificationsByType:(APPNotificationType)type
{
switch (type) {
case NotifcationTypeScheduled:
return [self getPendingNotifications];
case NotifcationTypeTriggered:
return [self getDeliveredNotifications];
default:
return [self getNotifications];
}
}
/**
* List of all local notifications IDs.
*/
- (NSArray*) getNotificationIds
{
NSArray* notifications = [self getNotifications];
NSMutableArray* ids = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
[ids addObject:notification.options.id];
}
return ids;
}
/**
* List of all notifications IDs from given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) getNotificationIdsByType:(APPNotificationType)type
{
NSArray* notifications = [self getNotificationsByType:type];
NSMutableArray* ids = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
[ids addObject:notification.options.id];
}
return ids;
}
/*
* If the notification with the specified ID does exists.
*
* @param id
* Notification ID
*/
- (BOOL) notificationExist:(NSNumber*)id
{
return [self getNotificationWithId:id] != NULL;
}
/* If the notification with specified ID and type exists.
*
* @param id
* Notification ID
* @param type
* Notification life cycle type
*/
- (BOOL) notificationExist:(NSNumber*)id type:(APPNotificationType)type
{
return [self getNotificationWithId:id andType:type] != NULL;
}
/**
* Find notification by ID.
*
* @param id
* Notification ID
*/
- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id
{
return [self getNotificationWithId:id andType:NotifcationTypeAll];
}
/*
* Find notification by ID and type.
*
* @param id
* Notification ID
* @param type
* Notification life cycle type
*/
- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id andType:(APPNotificationType)type
{
NSArray* notifications = [self getNotificationsByType:type];
for (UNNotificationRequest* notification in notifications)
{
NSString* fid = [NSString stringWithFormat:@"%@", notification.options.id];
if ([fid isEqualToString:[id stringValue]]) {
return notification;
}
}
return NULL;
}
/**
* List of properties from all notifications.
*/
- (NSArray*) getNotificationOptions
{
return [self getNotificationOptionsByType:NotifcationTypeAll];
}
/**
* List of properties from all notifications of given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type
{
NSArray* notifications = [self getNotificationsByType:type];
NSMutableArray* options = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
[options addObject:notification.options.userInfo];
}
return options;
}
/**
* List of properties from given local notifications.
*
* @param ids
* Notification IDs
*/
- (NSArray*) getNotificationOptionsById:(NSArray*)ids
{
return [self getNotificationOptionsByType:NotifcationTypeAll andId:ids];
}
/**
* List of properties from given local notifications.
*
* @param type
* Notification life cycle type
* @param ids
* Notification IDs
*/
- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type andId:(NSArray*)ids
{
NSArray* notifications = [self getNotificationsByType:type];
NSMutableArray* options = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
if ([ids containsObject:notification.options.id]) {
[options addObject:notification.options.userInfo];
}
}
return options;
}
/*
* Clear all notfications.
*/
- (void) clearAllNotifications
{
[self removeAllDeliveredNotifications];
}
/*
* Clear Specified notfication.
*
* @param notification
* The notification object
*/
- (void) clearNotification:(UNNotificationRequest*)notification
{
NSArray* ids = [[NSArray alloc]
initWithObjects:notification.identifier, nil];
[self removeDeliveredNotificationsWithIdentifiers:ids];
}
/*
* Cancel all notfications.
*/
- (void) cancelAllNotifications
{
[self removeAllPendingNotificationRequests];
[self removeAllDeliveredNotifications];
}
/*
* Cancel specified notfication.
*
* @param notification
* The notification object
*/
- (void) cancelNotification:(UNNotificationRequest*)notification
{
NSArray* ids = [[NSArray alloc]
initWithObjects:notification.identifier, nil];
[self removeDeliveredNotificationsWithIdentifiers:ids];
[self removePendingNotificationRequestsWithIdentifiers:ids];
}
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import <Foundation/Foundation.h>
#import <Cordova/CDVPlugin.h>
@interface APPLocalNotification9 : CDVPlugin
// Execute all queued events
- (void) deviceready:(CDVInvokedUrlCommand*)command;
// Inform if the app has the permission to show notifications
- (void) hasPermission:(CDVInvokedUrlCommand*)command;
// Register permission to show notifications
- (void) registerPermission:(CDVInvokedUrlCommand*)command;
// Schedule set of notifications
- (void) schedule:(CDVInvokedUrlCommand*)command;
// Update set of notifications
- (void) update:(CDVInvokedUrlCommand*)command;
// Cancel set of notifications
- (void) cancel:(CDVInvokedUrlCommand*)command;
// Cancel all notifications
- (void) cancelAll:(CDVInvokedUrlCommand*)command;
// Clear set of notifications
- (void) clear:(CDVInvokedUrlCommand*)command;
// Clear all notifications
- (void) clearAll:(CDVInvokedUrlCommand*)command;
// If a notification with an ID is present
- (void) isPresent:(CDVInvokedUrlCommand*)command;
// If a notification with an ID is scheduled
- (void) isScheduled:(CDVInvokedUrlCommand*)command;
// If a notification with an ID is triggered
- (void) isTriggered:(CDVInvokedUrlCommand*)command;
// List all ids from all local notifications
- (void) getAllIds:(CDVInvokedUrlCommand*)command;
// List all ids from all pending notifications
- (void) getScheduledIds:(CDVInvokedUrlCommand*)command;
// List all ids from all triggered notifications
- (void) getTriggeredIds:(CDVInvokedUrlCommand*)command;
// Propertys for given local notification
- (void) getSingle:(CDVInvokedUrlCommand*)command;
// Propertya for given scheduled notification
- (void) getSingleScheduled:(CDVInvokedUrlCommand*)command;
// Propertys for given triggered notification
- (void) getSingleTriggered:(CDVInvokedUrlCommand*)command;
// Property list for given local notifications
- (void) getAll:(CDVInvokedUrlCommand*)command;
// Property list for given scheduled notifications
- (void) getScheduled:(CDVInvokedUrlCommand*)command;
// Property list for given triggered notifications
- (void) getTriggered:(CDVInvokedUrlCommand*)command;
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "APPLocalNotification.ios9.h"
#import "APPLocalNotificationOptions.ios9.h"
#import "UIApplication+APPLocalNotification.ios9.h"
#import "UILocalNotification+APPLocalNotification.ios9.h"
@interface APPLocalNotification9 ()
// Retrieves the application state
@property (readonly, getter=applicationState) NSString* applicationState;
// All events will be queued until deviceready has been fired
@property (readwrite, assign) BOOL deviceready;
// Event queue
@property (readonly, nonatomic, retain) NSMutableArray* eventQueue;
// Needed when calling `registerPermission`
@property (nonatomic, retain) CDVInvokedUrlCommand* command;
@end
@implementation APPLocalNotification9
@synthesize deviceready, eventQueue;
#pragma mark -
#pragma mark Interface
/**
* Execute all queued events.
*/
- (void) deviceready:(CDVInvokedUrlCommand*)command
{
deviceready = YES;
for (NSString* js in eventQueue) {
[self.commandDelegate evalJs:js];
}
[eventQueue removeAllObjects];
}
/**
* Schedule a set of notifications.
*
* @param properties
* A dict of properties for each notification
*/
- (void) schedule:(CDVInvokedUrlCommand*)command
{
NSArray* notifications = command.arguments;
[self.commandDelegate runInBackground:^{
for (NSDictionary* options in notifications) {
UILocalNotification* notification;
notification = [[UILocalNotification alloc]
initWithOptions:options];
[self scheduleLocalNotification:[notification copy]];
[self fireEvent:@"schedule" notification:notification];
if (notifications.count > 1) {
[NSThread sleepForTimeInterval:0.01];
}
}
[self execCallback:command];
}];
}
/**
* Update a set of notifications.
*
* @param properties
* A dict of properties for each notification
*/
- (void) update:(CDVInvokedUrlCommand*)command
{
NSArray* notifications = command.arguments;
[self.commandDelegate runInBackground:^{
for (NSDictionary* options in notifications) {
NSNumber* id = [options objectForKey:@"id"];
UILocalNotification* notification;
notification = [self.app localNotificationWithId:id];
if (!notification)
continue;
[self updateLocalNotification:[notification copy]
withOptions:options];
[self fireEvent:@"update" notification:notification];
if (notifications.count > 1) {
[NSThread sleepForTimeInterval:0.01];
}
}
[self execCallback:command];
}];
}
/**
* Cancel a set of notifications.
*
* @param ids
* The IDs of the notifications
*/
- (void) cancel:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
for (NSNumber* id in command.arguments) {
UILocalNotification* notification;
notification = [self.app localNotificationWithId:id];
if (!notification)
continue;
[self.app cancelLocalNotification:notification];
[self fireEvent:@"cancel" notification:notification];
}
[self execCallback:command];
}];
}
/**
* Cancel all local notifications.
*/
- (void) cancelAll:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
[self cancelAllLocalNotifications];
[self fireEvent:@"cancelall"];
[self execCallback:command];
}];
}
/**
* Clear a set of notifications.
*
* @param ids
* The IDs of the notifications
*/
- (void) clear:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
for (NSNumber* id in command.arguments) {
UILocalNotification* notification;
notification = [self.app localNotificationWithId:id];
if (!notification)
continue;
[self.app clearLocalNotification:notification];
[self fireEvent:@"clear" notification:notification];
}
[self execCallback:command];
}];
}
/**
* Clear all local notifications.
*/
- (void) clearAll:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
[self clearAllLocalNotifications];
[self fireEvent:@"clearall"];
[self execCallback:command];
}];
}
/**
* If a notification by ID is present.
*
* @param id
* The ID of the notification
*/
- (void) isPresent:(CDVInvokedUrlCommand *)command
{
[self isPresent:command type:NotifcationTypeAll];
}
/**
* If a notification by ID is scheduled.
*
* @param id
* The ID of the notification
*/
- (void) isScheduled:(CDVInvokedUrlCommand*)command
{
[self isPresent:command type:NotifcationTypeScheduled];
}
/**
* Check if a notification with an ID is triggered.
*
* @param id
* The ID of the notification
*/
- (void) isTriggered:(CDVInvokedUrlCommand*)command
{
[self isPresent:command type:NotifcationTypeTriggered];
}
/**
* Check if a notification with an ID exists.
*
* @param type
* The notification life cycle type
*/
- (void) isPresent:(CDVInvokedUrlCommand*)command
type:(APPNotificationType)type;
{
[self.commandDelegate runInBackground:^{
NSNumber* id = [command argumentAtIndex:0];
BOOL exist;
CDVPluginResult* result;
if (type == NotifcationTypeAll) {
exist = [self.app localNotificationExist:id];
} else {
exist = [self.app localNotificationExist:id type:type];
}
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:exist];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
/**
* List all ids from all local notifications.
*/
- (void) getAllIds:(CDVInvokedUrlCommand*)command
{
[self getIds:command byType:NotifcationTypeAll];
}
/**
* List all ids from all pending notifications.
*/
- (void) getScheduledIds:(CDVInvokedUrlCommand*)command
{
[self getIds:command byType:NotifcationTypeScheduled];
}
/**
* List all ids from all triggered notifications.
*/
- (void) getTriggeredIds:(CDVInvokedUrlCommand*)command
{
[self getIds:command byType:NotifcationTypeTriggered];
}
/**
* List of ids for given local notifications.
*
* @param type
* Notification life cycle type
* @param ids
* The IDs of the notifications
*/
- (void) getIds:(CDVInvokedUrlCommand*)command
byType:(APPNotificationType)type;
{
[self.commandDelegate runInBackground:^{
CDVPluginResult* result;
NSArray* ids;
if (type == NotifcationTypeAll) {
ids = [self.app localNotificationIds];
} else {
ids = [self.app localNotificationIdsByType:type];
}
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:ids];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
/**
* Propertys for given local notification.
*/
- (void) getSingle:(CDVInvokedUrlCommand*)command
{
[self getOption:command byType:NotifcationTypeAll];
}
/**
* Propertya for given scheduled notification.
*/
- (void) getSingleScheduled:(CDVInvokedUrlCommand*)command
{
[self getOption:command byType:NotifcationTypeScheduled];
}
// Propertys for given triggered notification
- (void) getSingleTriggered:(CDVInvokedUrlCommand*)command
{
[self getOption:command byType:NotifcationTypeTriggered];
}
/**
* Property list for given local notifications.
*
* @param ids
* The IDs of the notifications
*/
- (void) getAll:(CDVInvokedUrlCommand*)command
{
[self getOptions:command byType:NotifcationTypeAll];
}
/**
* Property list for given scheduled notifications.
*
* @param ids
* The IDs of the notifications
*/
- (void) getScheduled:(CDVInvokedUrlCommand*)command
{
[self getOptions:command byType:NotifcationTypeScheduled];
}
/**
* Property list for given triggered notifications.
*
* @param ids
* The IDs of the notifications
*/
- (void) getTriggered:(CDVInvokedUrlCommand *)command
{
[self getOptions:command byType:NotifcationTypeTriggered];
}
/**
* Propertys for given triggered notification.
*
* @param type
* Notification life cycle type
* @param ids
* The ID of the notification
*/
- (void) getOption:(CDVInvokedUrlCommand*)command
byType:(APPNotificationType)type;
{
[self.commandDelegate runInBackground:^{
NSArray* ids = command.arguments;
NSArray* notifications;
CDVPluginResult* result;
if (type == NotifcationTypeAll) {
notifications = [self.app localNotificationOptionsById:ids];
}
else {
notifications = [self.app localNotificationOptionsByType:type
andId:ids];
}
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:[notifications firstObject]];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
/**
* Property list for given triggered notifications.
*
* @param type
* Notification life cycle type
* @param ids
* The IDs of the notifications
*/
- (void) getOptions:(CDVInvokedUrlCommand*)command
byType:(APPNotificationType)type;
{
[self.commandDelegate runInBackground:^{
NSArray* ids = command.arguments;
NSArray* notifications;
CDVPluginResult* result;
if (type == NotifcationTypeAll && ids.count == 0) {
notifications = [self.app localNotificationOptions];
}
else if (type == NotifcationTypeAll) {
notifications = [self.app localNotificationOptionsById:ids];
}
else if (ids.count == 0) {
notifications = [self.app localNotificationOptionsByType:type];
}
else {
notifications = [self.app localNotificationOptionsByType:type
andId:ids];
}
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:notifications];
[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 = [self.app hasPermissionToScheduleLocalNotifications];
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:hasPermission];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
/**
* Ask for permission to show badges.
*/
- (void) registerPermission:(CDVInvokedUrlCommand*)command
{
if ([[UIApplication sharedApplication]
respondsToSelector:@selector(registerUserNotificationSettings:)])
{
_command = command;
[self.commandDelegate runInBackground:^{
[self.app registerPermissionToScheduleLocalNotifications];
}];
} else {
[self hasPermission:command];
}
}
#pragma mark -
#pragma mark Core Logic
/**
* Schedule the local notification.
*/
- (void) scheduleLocalNotification:(UILocalNotification*)notification
{
[self cancelForerunnerLocalNotification:notification];
[self.app scheduleLocalNotification:notification];
}
/**
* Update the local notification.
*/
- (void) updateLocalNotification:(UILocalNotification*)notification
withOptions:(NSDictionary*)newOptions
{
NSMutableDictionary* options = [notification.userInfo mutableCopy];
[options addEntriesFromDictionary:newOptions];
[options setObject:[NSDate date] forKey:@"updatedAt"];
notification = [[UILocalNotification alloc]
initWithOptions:options];
[self scheduleLocalNotification:notification];
}
/**
* Cancel all local notifications.
*/
- (void) cancelAllLocalNotifications
{
[self.app cancelAllLocalNotifications];
[self.app setApplicationIconBadgeNumber:0];
}
/**
* Clear all local notifications.
*/
- (void) clearAllLocalNotifications
{
[self.app clearAllLocalNotifications];
[self.app setApplicationIconBadgeNumber:0];
}
/**
* Cancel a maybe given forerunner with the same ID.
*/
- (void) cancelForerunnerLocalNotification:(UILocalNotification*)notification
{
NSNumber* id = notification.options.id;
UILocalNotification* forerunner;
forerunner = [self.app localNotificationWithId:id];
if (!forerunner)
return;
[self.app cancelLocalNotification:forerunner];
}
/**
* Cancels all non-repeating local notification older then
* a specific amount of seconds
*/
- (void) cancelAllNotificationsWhichAreOlderThen:(float)seconds
{
NSArray* notifications;
notifications = [self.app localNotifications];
for (UILocalNotification* notification in notifications)
{
if (![notification isRepeating]
&& notification.timeIntervalSinceFireDate > seconds)
{
[self.app cancelLocalNotification:notification];
[self fireEvent:@"cancel" notification:notification];
}
}
}
#pragma mark -
#pragma mark Delegates
/**
* Calls the cancel or trigger event after a local notification was received.
* Cancels the local notification if autoCancel was set to true.
*/
- (void) didReceiveLocalNotification:(NSNotification*)localNotification
{
UILocalNotification* notification = [localNotification object];
if ([notification userInfo] == NULL || [notification wasUpdated])
return;
NSTimeInterval timeInterval = [notification timeIntervalSinceLastTrigger];
NSString* event = timeInterval < 0.2 && deviceready ? @"trigger" : @"click";
[self fireEvent:event notification:notification];
if (![event isEqualToString:@"click"])
return;
if ([notification isRepeating]) {
[self fireEvent:@"clear" notification:notification];
} else {
[self.app cancelLocalNotification:notification];
[self fireEvent:@"cancel" notification:notification];
}
}
/**
* Called when app has started
* (by clicking on a local notification).
*/
- (void) didFinishLaunchingWithOptions:(NSNotification*)notification
{
NSDictionary* launchOptions = [notification userInfo];
UILocalNotification* localNotification;
localNotification = [launchOptions objectForKey:
UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotification) {
[self didReceiveLocalNotification:
[NSNotification notificationWithName:CDVLocalNotification
object:localNotification]];
}
}
/**
* Called on otification settings registration is completed.
*/
- (void) didRegisterUserNotificationSettings:(UIUserNotificationSettings*)settings
{
if (_command) {
[self hasPermission:_command];
_command = NULL;
}
}
#pragma mark -
#pragma mark Life Cycle
/**
* Registers obervers after plugin was initialized.
*/
- (void) pluginInitialize
{
eventQueue = [[NSMutableArray alloc] init];
}
/**
* Clears all single repeating notifications which are older then 5 days
* before the app terminates.
*/
- (void) onAppTerminate
{
[self cancelAllNotificationsWhichAreOlderThen:432000];
}
#pragma mark -
#pragma mark Helper
/**
* Retrieves the application state
*
* @return
* Either "background" or "foreground"
*/
- (NSString*) applicationState
{
UIApplicationState state = [self.app applicationState];
bool isActive = state == UIApplicationStateActive;
return isActive ? @"foreground" : @"background";
}
/**
* Simply invokes the callback without any parameter.
*/
- (void) execCallback:(CDVInvokedUrlCommand*)command
{
CDVPluginResult *result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}
/**
* Short hand for shared application instance.
*/
- (UIApplication*) app
{
return [UIApplication sharedApplication];
}
/**
* Fire general event.
*/
- (void) fireEvent:(NSString*)event
{
[self fireEvent:event notification:NULL];
}
/**
* Fire event for local notification.
*/
- (void) fireEvent:(NSString*)event notification:(UILocalNotification*)notification
{
NSString* js;
NSString* params = [NSString stringWithFormat:
@"\"%@\"", self.applicationState];
if (notification) {
NSString* args = [notification encodeToJSON];
params = [NSString stringWithFormat:
@"%@,'%@'",
args, self.applicationState];
}
js = [NSString stringWithFormat:
@"cordova.plugins.notification.local.core.fireEvent('%@', %@)",
event, params];
if (deviceready) {
[self.commandDelegate evalJs:js];
} else {
[self.eventQueue addObject:js];
}
}
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface APPLocalNotificationOptions9 : NSObject
- (id) initWithDict:(NSDictionary*)dict;
@property (readonly, getter=id) NSNumber* id;
@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;
// If it's a repeating notification
- (BOOL) isRepeating;
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "APPLocalNotificationOptions.ios9.h"
@interface APPLocalNotificationOptions9 ()
// The dictionary which contains all notification properties
@property(nonatomic, retain) NSDictionary* dict;
@end
@implementation APPLocalNotificationOptions9
@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 = [self init];
self.dict = dictionary;
return self;
}
#pragma mark -
#pragma mark Attributes
/**
* The notification's ID.
*/
- (NSNumber*) id
{
NSInteger id = [[dict objectForKey:@"id"] integerValue];
return [NSNumber numberWithInteger:id];
}
/**
* The notification's title.
*/
- (NSString*) title
{
return [dict objectForKey:@"title"];
}
/**
* The notification's message.
*/
- (NSString*) text
{
return [dict objectForKey:@"text"];
}
/**
* 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 text];
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 ([self stringIsNullOrEmpty:path])
return NULL;
if ([path isEqualToString:@"res://platform_default"])
return UILocalNotificationDefaultSoundName;
if ([path hasPrefix:@"file:/"])
return [self soundNameForAsset:path];
if ([path hasPrefix:@"res:"])
return [self soundNameForResource:path];
return NULL;
}
/**
* The notification's fire date.
*/
- (NSDate*) fireDate
{
double timestamp = [[dict objectForKey:@"at"]
doubleValue];
return [NSDate dateWithTimeIntervalSince1970:timestamp];
}
/**
* The notification's repeat interval.
*/
- (NSCalendarUnit) repeatInterval
{
NSString* interval = [dict objectForKey:@"every"];
if ([self stringIsNullOrEmpty:interval]) {
return NSCalendarUnitEra;
}
else if ([interval isEqualToString:@"second"]) {
return NSCalendarUnitSecond;
}
else if ([interval isEqualToString:@"minute"]) {
return NSCalendarUnitMinute;
}
else if ([interval isEqualToString:@"hour"]) {
return NSCalendarUnitHour;
}
else if ([interval isEqualToString:@"day"]) {
return NSCalendarUnitDay;
}
else if ([interval isEqualToString:@"week"]) {
return NSCalendarUnitWeekOfYear;
}
else if ([interval isEqualToString:@"month"]) {
return NSCalendarUnitMonth;
}
else if ([interval isEqualToString:@"quarter"]) {
return NSCalendarUnitQuarter;
}
else if ([interval isEqualToString:@"year"]) {
return NSCalendarUnitYear;
}
return NSCalendarUnitEra;
}
#pragma mark -
#pragma mark Methods
/**
* The notification's user info dict.
*/
- (NSDictionary*) userInfo
{
if ([dict objectForKey:@"updatedAt"]) {
NSMutableDictionary* data = [dict mutableCopy];
[data removeObjectForKey:@"updatedAt"];
return data;
}
return dict;
}
/**
* If it's a repeating notification.
*/
- (BOOL) isRepeating
{
NSCalendarUnit interval = self.repeatInterval;
return !(interval == NSCalendarUnitEra || interval == 0);
}
#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
......@@ -21,7 +21,7 @@
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "UILocalNotification+APPLocalNotification.h"
#import "UILocalNotification+APPLocalNotification.ios9.h"
@interface UIApplication (APPLocalNotification)
......@@ -34,26 +34,26 @@
- (void) registerPermissionToScheduleLocalNotifications;
// List of all local notification IDs from given type
- (NSArray*) localNotificationIdsByType:(APPLocalNotificationType)type;
- (NSArray*) localNotificationIdsByType:(APPNotificationType)type;
// If local notification with ID exists
- (BOOL) localNotificationExist:(NSNumber*)id;
// If local notification with ID and type exists
- (BOOL) localNotificationExist:(NSNumber*)id type:(APPLocalNotificationType)type;
- (BOOL) localNotificationExist:(NSNumber*)id type:(APPNotificationType)type;
// Local notification by ID
- (UILocalNotification*) localNotificationWithId:(NSNumber*)id;
// Local notification by ID and type
- (UILocalNotification*) localNotificationWithId:(NSNumber*)id andType:(APPLocalNotificationType)type;
- (UILocalNotification*) localNotificationWithId:(NSNumber*)id andType:(APPNotificationType)type;
// Property list from all local notifications
- (NSArray*) localNotificationOptions;
// Property list from given local notifications
- (NSArray*) localNotificationOptionsById:(NSArray*)ids;
// Property list from all local notifications with type constraint
- (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type;
- (NSArray*) localNotificationOptionsByType:(APPNotificationType)type;
// Property list from given local notifications with type constraint
- (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type andId:(NSArray*)ids;
- (NSArray*) localNotificationOptionsByType:(APPNotificationType)type andId:(NSArray*)ids;
// Clear single local notfications
- (void) clearLocalNotification:(UILocalNotification*)notification;
......
......@@ -21,8 +21,8 @@
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "UIApplication+APPLocalNotification.h"
#import "UILocalNotification+APPLocalNotification.h"
#import "UIApplication+APPLocalNotification.ios9.h"
#import "UILocalNotification+APPLocalNotification.ios9.h"
@implementation UIApplication (APPLocalNotification)
......@@ -138,7 +138,7 @@
* @param type
* Notification life cycle type
*/
- (NSArray*) localNotificationIdsByType:(APPLocalNotificationType)type
- (NSArray*) localNotificationIdsByType:(APPNotificationType)type
{
NSArray* notifications = self.localNotifications;
NSMutableArray* ids = [[NSMutableArray alloc] init];
......@@ -171,7 +171,7 @@
* @param type
* Notification life cycle type
*/
- (BOOL) localNotificationExist:(NSNumber*)id type:(APPLocalNotificationType)type
- (BOOL) localNotificationExist:(NSNumber*)id type:(APPNotificationType)type
{
return [self localNotificationWithId:id andType:type] != NULL;
}
......@@ -206,7 +206,7 @@
* @param type
* Notification life cycle type
*/
- (UILocalNotification*) localNotificationWithId:(NSNumber*)id andType:(APPLocalNotificationType)type
- (UILocalNotification*) localNotificationWithId:(NSNumber*)id andType:(APPNotificationType)type
{
UILocalNotification* notification = [self localNotificationWithId:id];
......@@ -238,7 +238,7 @@
* @param type
* Notification life cycle type
*/
- (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type
- (NSArray*) localNotificationOptionsByType:(APPNotificationType)type
{
NSArray* notifications = self.localNotifications;
NSMutableArray* options = [[NSMutableArray alloc] init];
......@@ -284,7 +284,7 @@
* @param ids
* Notification IDs
*/
- (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type andId:(NSArray*)ids
- (NSArray*) localNotificationOptionsByType:(APPNotificationType)type andId:(NSArray*)ids
{
UILocalNotification* notification;
NSMutableArray* options = [[NSMutableArray alloc] init];
......
......@@ -21,20 +21,22 @@
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "APPLocalNotificationOptions.h"
#import "APPLocalNotificationOptions.ios9.h"
typedef NS_ENUM(NSUInteger, APPLocalNotificationType) {
#ifndef APPNotificationType_DEFINED
typedef NS_ENUM(NSUInteger, APPNotificationType) {
NotifcationTypeAll = 0,
NotifcationTypeScheduled = 1,
NotifcationTypeTriggered = 2
};
#endif
@interface UILocalNotification (APPLocalNotification)
// Initialize a new local notification
- (id) initWithOptions:(NSDictionary*)dict;
// The options provided by the plug-in
- (APPLocalNotificationOptions*) options;
- (APPLocalNotificationOptions9*) options;
// Timeinterval since last trigger date
- (double) timeIntervalSinceLastTrigger;
// Timeinterval since fire date
......@@ -50,7 +52,7 @@ typedef NS_ENUM(NSUInteger, APPLocalNotificationType) {
// If it's a repeating notification
- (BOOL) isRepeating;
// Notifciation type
- (APPLocalNotificationType) type;
- (APPNotificationType) type;
// Encode the user info dict to JSON
- (NSString*) encodeToJSON;
......
......@@ -21,8 +21,8 @@
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "UILocalNotification+APPLocalNotification.h"
#import "APPLocalNotificationOptions.h"
#import "UILocalNotification+APPLocalNotification.ios9.h"
#import "APPLocalNotificationOptions.ios9.h"
#import <objc/runtime.h>
static char optionsKey;
......@@ -56,7 +56,7 @@ NSInteger const APPLocalNotificationTypeTriggered = 2;
*/
- (void) __init
{
APPLocalNotificationOptions* options = self.options;
APPLocalNotificationOptions9* options = self.options;
self.fireDate = options.fireDate;
self.timeZone = [NSTimeZone defaultTimeZone];
......@@ -76,12 +76,12 @@ NSInteger const APPLocalNotificationTypeTriggered = 2;
/**
* The options provided by the plug-in.
*/
- (APPLocalNotificationOptions*) options
- (APPLocalNotificationOptions9*) options
{
APPLocalNotificationOptions* options = [self getOptions];
APPLocalNotificationOptions9* options = [self getOptions];
if (!options) {
options = [[APPLocalNotificationOptions alloc]
options = [[APPLocalNotificationOptions9 alloc]
initWithDict:[self userInfo]];
[self setOptions:options];
......@@ -93,7 +93,7 @@ NSInteger const APPLocalNotificationTypeTriggered = 2;
/**
* Get associated option object
*/
- (APPLocalNotificationOptions*) getOptions
- (APPLocalNotificationOptions9*) getOptions
{
return objc_getAssociatedObject(self, &optionsKey);
}
......@@ -101,7 +101,7 @@ NSInteger const APPLocalNotificationTypeTriggered = 2;
/**
* Set associated option object
*/
- (void) setOptions:(APPLocalNotificationOptions*)options
- (void) setOptions:(APPLocalNotificationOptions9*)options
{
objc_setAssociatedObject(self, &optionsKey,
options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
......@@ -239,7 +239,7 @@ NSInteger const APPLocalNotificationTypeTriggered = 2;
/**
* Process state type of the local notification.
*/
- (APPLocalNotificationType) type
- (APPNotificationType) type
{
return [self isTriggered] ? NotifcationTypeTriggered : NotifcationTypeScheduled;
}
......
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