Saturday, April 10, 2010

Local Notification Sample Code (OS 4.0 only)

Start a new Window-based Application Project called LocalPush

Add an instance variable bgTask in LocalPushAppDelegate


@interface LocalPushAppDelegate : NSObject {
    UIWindow *window;
    UIBackgroundTaskIdentifier bgTask;
}


It will fire up a Local Notification to remind you one min before the event which is 2 minutes due from now

LocalPushAppDelegate.m Select all

//
// LocalPushAppDelegate.m
// LocalPush
//

@interface ToDoItem : NSObject {
NSInteger year;
NSInteger month;
NSInteger day;
NSInteger hour;
NSInteger minute;
NSInteger second;
NSString *eventName;
}

@property (nonatomic, readwrite) NSInteger year;
@property (nonatomic, readwrite) NSInteger month;
@property (nonatomic, readwrite) NSInteger day;
@property (nonatomic, readwrite) NSInteger hour;
@property (nonatomic, readwrite) NSInteger minute;
@property (nonatomic, readwrite) NSInteger second;
@property (nonatomic, copy) NSString *eventName;

@end

@implementation ToDoItem

@synthesize year, month, day, hour, minute, second, eventName;

@end

#import "LocalPushAppDelegate.h"

@implementation LocalPushAppDelegate

@synthesize window;

#define ToDoItemKey @"EVENTKEY1"
#define MessageTitleKey @"MSGKEY1"


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(@"application: didFinishLaunchingWithOptions:");
// Override point for customization after application launch

UILocalNotification *localNotif = [launchOptions
objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];

if (localNotif) {
NSString *itemName = [localNotif.userInfo objectForKey:ToDoItemKey];
// [viewController displayItem:itemName]; // custom method
application.applicationIconBadgeNumber = localNotif.applicationIconBadgeNumber-1;
NSLog(@"has localNotif %@",itemName);
}
else {
[[UIApplication sharedApplication] cancelAllLocalNotifications];
NSDate *now = [NSDate date];
NSLog(@"now is %@",now);
NSDate *scheduled = [now dateByAddingTimeInterval:120] ; //get x minute after
NSCalendar *calendar = [NSCalendar currentCalendar];

unsigned int unitFlags = NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit;
NSDateComponents *comp = [calendar components:unitFlags fromDate:scheduled];

NSLog(@"scheduled is %@",scheduled);

ToDoItem *todoitem = [[ToDoItem alloc] init];

todoitem.day = [comp day];
todoitem.month = [comp month];
todoitem.year = [comp year];
todoitem.hour = [comp hour];
todoitem.minute = [comp minute];
todoitem.eventName = @"Testing Event";

[self scheduleNotificationWithItem:todoitem interval:1];
NSLog(@"scheduleNotificationWithItem");
}
[window makeKeyAndVisible];
return YES;
}

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notif {
NSLog(@"application: didReceiveLocalNotification:");
NSString *itemName = [notif.userInfo objectForKey:ToDoItemKey];
NSString *messageTitle = [notif.userInfo objectForKey:MessageTitleKey];
// [viewController displayItem:itemName]; // custom method
[self _showAlert:itemName withTitle:messageTitle];
NSLog(@"Receive Local Notification while the app is still running...");
NSLog(@"current notification is %@",notif);
application.applicationIconBadgeNumber = notif.applicationIconBadgeNumber-1;

}

- (void) _showAlert:(NSString*)pushmessage withTitle:(NSString*)title
{

UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:title message:pushmessage delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
if (alertView) {
[alertView release];
}
}


- (void)scheduleNotificationWithItem:(ToDoItem *)item interval:(int)minutesBefore {
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
NSDateComponents *dateComps = [[NSDateComponents alloc] init];
[dateComps setDay:item.day];
[dateComps setMonth:item.month];
[dateComps setYear:item.year];
[dateComps setHour:item.hour];
[dateComps setMinute:item.minute];
NSDate *itemDate = [calendar dateFromComponents:dateComps];
[dateComps release];


UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = [itemDate dateByAddingTimeInterval:-(minutesBefore*60)];
NSLog(@"fireDate is %@",localNotif.fireDate);
localNotif.timeZone = [NSTimeZone defaultTimeZone];

localNotif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"%@ in %i minutes.", nil),
item.eventName, minutesBefore];
localNotif.alertAction = NSLocalizedString(@"View Details", nil);

localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 1;
// NSDictionary *infoDict = [NSDictionary dictionaryWithObject:item.eventName forKey:ToDoItemKey];
NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys:item.eventName,ToDoItemKey, @"Local Push received while running", MessageTitleKey, nil];
localNotif.userInfo = infoDict;

[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
NSLog(@"scheduledLocalNotifications are %@", [[UIApplication sharedApplication] scheduledLocalNotifications]);
[localNotif release];
}

- (NSString *) checkForIncomingChat {
return @"javacom";
};

- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(@"Application entered background state.");
// UIBackgroundTaskIdentifier bgTask is instance variable
// UIInvalidBackgroundTask has been renamed to UIBackgroundTaskInvalid
NSAssert(self->bgTask == UIBackgroundTaskInvalid, nil);

bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{
dispatch_async(dispatch_get_main_queue(), ^{
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}];

dispatch_async(dispatch_get_main_queue(), ^{
while ([application backgroundTimeRemaining] > 1.0) {
NSString *friend = [self checkForIncomingChat];
if (friend) {
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif) {
localNotif.alertBody = [NSString stringWithFormat:
NSLocalizedString(@"%@ has a message for you.", nil), friend];
localNotif.alertAction = NSLocalizedString(@"Read Msg", nil);
localNotif.soundName = @"alarmsound.caf";
localNotif.applicationIconBadgeNumber = 1;
NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys:@"Your Background Task works",ToDoItemKey, @"Message from javacom", MessageTitleKey, nil];
localNotif.userInfo = infoDict;
[application presentLocalNotificationNow:localNotif];
[localNotif release];
friend = nil;
break;
}
}
}
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}


- (void)dealloc {
[window release];
[super dealloc];
}


@end




.
.
.

19 comments:

Dave said...

Do you know if there's a way of having a custom repeat interval? I see the built-in NSCalendarUnits, but I'm looking for something custom, like say 45 minutes or something. Any ideas? Everything I try sends the phone in a constant reboot loop.

Apple Geek said...

Thanks for the tutorial. A few more comments in the code would be very helpful though.

Apple Geek said...

Hey thanks for the great tutorial! How do you set a defined time for the alert to go off? I know this is a basic question but I would appreciate the help! Thanks

Jeroen de Leeuw said...

Do you know for how long the application can remain active in the background?

apiphone said...

Hello, thanks for the code. Where did you find the documentation of UILocalNotification class. There is no documentation available on iphone dev center web site. Don't know what methods/properties are there. Can you please point me to the location.

Thanks

Allen said...

Amazing tutorial.What is application activation time?

Anonymous said...

When I try to run this code I get an error:
'UIInvalidBackgroundTask' undeclared

Not sure what is going on since I just copied and pasted your code. My code base is 4.0, any ideas? Thanks.

Anonymous said...

That's because UIInvalidBackgroundTask has been renamed UIBackgroundTaskInvalid. Change all instances of the former to the latter and you'll be fine.

manoj said...

Thanks for the tutorial. A comments list would be very helpful. :)

sukhi said...

when i pressed home button it shows alert view when i pressed OK application terminated and when i pressed close application remain in background but when i reopen it application again terminated ... what to do now please tell...

intern said...

in my application after setting some time say 5 min i want to pop up message with ok button which is already running in background task and even someone press ok button again it should display the message means someone cannot do anything after setting time in my applicaiton.please help me how can i do it

Anonymous said...

suppose two notifications at the same time?what about popup box,is it one below another?

srinu said...

how can we set custom repeat interval as 2days or 3 days in schedule Notification......
i m using Nscalender For Getting Update date for notification firing

Anonymous said...

Good tutorial. In my application i want to fire local notifications only for 3 days. After 3 days i want to remove the notification. Any idea, how to set the interval only for 3 days?. Any help is highly appreciated.

Thanks

Anonymous said...

Thank's for the code...
You forgot to release todoitem in didFinishLaunchingWithOptions

Anonymous said...

has anybody used a solution for push notifications by Appoxee? let me know

Sukumar Jena said...

Thanks for everyone for giving your valuable information on this topic..

Thanks to all

Mritunjay Kumar said...

Thanks for Giving the Tutorial...

Steve Paul said...

Thanks for sharing keep it up ! emergency notification