IOS local notifications with Cordova v3+

Andrew Dahlman’s local notifications plug in is a life saver. He’s bridged the gap between the native Objective-C library and your standard JavaScript app sitting in the web view wrapper. I know that he submitted the plug in to the official Phonegap build but I’m not sure if it made it in. It should!

Like many open source projects, the original writer can’t stay on the project forever. When updates to dependencies occur software can become difficult to install/use. Such is the case with this amazingly useful code collection.

So I’m writing this post in order to document some of the issues I ran into along with some solutions. Feel free to comment, correct, or add to the show.

*Note: These are all Objective-C or Xml changes. The Javascript source gave me no issues at all.

1. The plist paradigm has been replaced with config.xml. The read me files refer to a plist file a few times and this can throw some folks off. There was at least one person on the GIT thread that mentioned this.

With the switch to config.xml comes the XML syntax.

<feature name="LocalNotification">
 <param name="ios-package" value="LocalNotification" />
 </feature>

2. The Cordova 2.3.0+ implementation is was missing the badge feature that Andrew had made available in the original Phonegap version. If you find local notifications useful for your app then putting badge numbers on the app icon seems pretty clutch so I added it. Line 16 inserts the badge option while lines 18-19 are for the background and foreground callback features that I personally did not need and left them commented. 


-(void)addNotification:(CDVInvokedUrlCommand*)command {

 NSMutableDictionary *repeatDict = [[NSMutableDictionary alloc] init];
 [repeatDict setObject:[NSNumber numberWithInt:NSDayCalendarUnit ] forKey:@"daily" ];
 [repeatDict setObject:[NSNumber numberWithInt:NSWeekCalendarUnit ] forKey:@"weekly" ];
 [repeatDict setObject:[NSNumber numberWithInt:NSMonthCalendarUnit ] forKey:@"monthly" ];
 [repeatDict setObject:[NSNumber numberWithInt:NSYearCalendarUnit ] forKey:@"yearly" ];
 [repeatDict setObject:[NSNumber numberWithInt:0 ] forKey:@"" ];

 UILocalNotification* notif = [[UILocalNotification alloc] init];

double fireDate = [[command.arguments objectAtIndex:0] doubleValue];
 NSString *alertBody = [command.arguments objectAtIndex:1];
 NSNumber *repeatInterval = [command.arguments objectAtIndex:2];
 NSString *soundName = [command.arguments objectAtIndex:3];
 NSNumber *badge = [command.arguments objectAtIndex:4];
 NSString *notificationId = [command.arguments objectAtIndex:5];
// NSString *bg = [command.arguments objectAtIndex:6];
// NSString *fg = [command.arguments objectAtIndex:7];

 notif.alertBody = ([alertBody isEqualToString:@""])?nil:alertBody;
 notif.fireDate = [NSDate dateWithTimeIntervalSince1970:fireDate];
 notif.repeatInterval = [[repeatDict objectForKey: repeatInterval] intValue];
 notif.soundName = soundName;
 notif.timeZone = [NSTimeZone defaultTimeZone];

 NSDictionary *userDict = [NSDictionary dictionaryWithObjectsAndKeys:
 notificationId , @"notificationId",
 command.callbackId, @"callbackId",
 nil
 ];

 notif.userInfo = userDict;

 [[UIApplication sharedApplication] scheduleLocalNotification:notif];

}

3. For some reason the call to the application object in the actual badge call was not working so I had to call it using the sharedApplication syntax instead.

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
 {

 UIApplicationState state = [application applicationState];
 if (state == UIApplicationStateActive) {
 // WAS RUNNING
 NSLog(@"I was currently active Selino");

 NSString *notCB = [notification.userInfo objectForKey:@"foreground"];
 NSString *notID = [notification.userInfo objectForKey:@"notificationId"];

 NSString * jsCallBack = [NSString
 stringWithFormat:@"%@(%@)", notCB,notID];

 [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsCallBack];

 //application.applicationIconBadgeNumber = 0;
 [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
 }
 else {
 // WAS IN BG
 NSLog(@"I was in the background");

 NSString *notCB = [notification.userInfo objectForKey:@"background"];
 NSString *notID = [notification.userInfo objectForKey:@"notificationId"];

 NSString * jsCallBack = [NSString
 stringWithFormat:@"%@(%@)", notCB,notID];
 [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsCallBack];

 //application.applicationIconBadgeNumber = 0;
 [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
 }
 }

4. Badges were removed from the Cordova plugin properties altogether. I mentioned that earlier. So I added a badge call into the cancel method and added an incrementBadge method.

- (void)cancelAllNotifications:(CDVInvokedUrlCommand*)command {
[[UIApplication sharedApplication] cancelAllLocalNotifications];</pre>
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
}

- (void)incrementBadge:(NSNotification *)notification {
int num = [UIApplication sharedApplication].applicationIconBadgeNumber;
[UIApplication sharedApplication].applicationIconBadgeNumber = num + 1;
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s