Im working on an app that does some computationally heavy tasks that take a long time. I want to notify the user with a local push notification when the task is done. Is this possible? The only information I have been able to find online is to do with triggering notifications at certain times/dates or if the app has entered the background or terminated, all of which is done in the appDelegate. Is there a way to do this in my own classes?
Thanks.
I'm not 100% certain you're looking for a UILocalNotification example because the post title mentions push notifications. Either way, you can schedule local notifications from any class you want
- (void)throwLocalNotificationWithMessage:(NSString*)message {
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
NSDate *now = [NSDate date];
localNotification.fireDate = now;
localNotification.alertBody = message;
localNotification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
[UIApplication sharedApplication].applicationIconBadgeNumber++;
}
Also, for my needs I throw these local notifications when region monitoring detects boundary enter/exit changes. This code runs while my app is in the background, as well, and in that case they appear like push notifications.
The above answer by Aaron works fine but don't forget to ask permission for Local Notification. In my case case I ask permission at AppDelegate under -
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
and here is the code for iOS8 and iOS9
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)]) {
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}
Related
I am generating Local notification when Push notification(Actionable) are received but app is closed or in background. I have used following code to generate local notification in objective-c.
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler {
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
// localNotification.fireDate = [NSDate date];
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.alertBody = #"Security settings enabled, tap to start the application";
localNotification.category = #"LOCAL_NOTIFICATION"; // Same as category identifier
// [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
}
1.When i drag notification trey down(Notification Center) not from alert it generate local notification fine in 1 sec.
2.But while press action from alert(while at home) it
it takes 3-4 seconds for local notification to appear.
Why there is time difference between action from alert(press action from home) and Notification center(swipe down notification trey)
generating local notification?
How to make it faster? Thanks in advance.
Try to use the presentLocalNotificationNow method instead of scheduleLocalNotification to make your notification fire instantly:
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
I am making an app in which user select time and video. When notification fire than I want that the select video should be played . How can i achieve that?
Here is my notification code.
-(void) scheduleLocalNotificationWithDate:(NSDate *)fireDate
{
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
localNotif.fireDate = fireDate;
localNotif.timeZone = [NSTimeZone localTimeZone];
localNotif.alertBody = #"Time to wake Up";
localNotif.alertAction = #"Show me";
localNotif.soundName = #"Tick-tock-sound.mp3";
localNotif.applicationIconBadgeNumber = 1;
localNotif.repeatInterval = NSCalendarUnitDay;
NSLog(#" date %lu",kCFCalendarUnitDay);
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}
Any Syggestion?
Your code for scheduling a local notification looks good. Probably you should also add some data in the userInfo property of the local notification, so that when it fires, you can check that property and do something different (play a specific video) according to the data inside the userInfo.
Example:
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:#"video1" forKey:#"videoName"];
localNotif.userInfo = infoDict;
Make sure that you also request user permission for using local notifications, otherwise the local notification will not fire.
Example:
UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
Now you need to handle the firing of the local notification when your app is in the 3 states: foreground, background/suspended and not running.
The app is running in the foreground. The local notification fires at the date you set it to. The following delegate method will get called by the system in AppDelegate:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
NSString *videoName = [notification.userInfo objectForKey:#"videoName"];
//do something, probably play your specific video
}
The app is running in the background or is suspended. The local notification is shown to the user (it fired at the date you set it to) and the user taps on it. The same delegate method as above (didReceiveLocalNotification) will get called by the system in AppDelegate:
The app is not running, the local notification is shown to the user (it fired at the date you set it to) and the user taps on it. The following delegate method will get called by the system in AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif)
{
//the app was launched by tapping on a local notification
NSString *videoName = [localNotif.userInfo objectForKey:#"videoName"];
// play your specific video
} else {
// the app wasn't launched by tapping on a local notification
// do your regular stuff here
}
}
I would recommend reading Apple's documentation regarding working with local notifications.
You can use the Media Player framework as recommended in Glorfindel's answer and you can find an example for playing a video in this StackOverflow answer.
Once the user opens your local notification, your app will be launched, and the - application:didFinishLaunchingWithOptions: of your UIApplicationDelegate will be called. The options dictionary will contain a UIApplicationLaunchOptionsLocalNotificationKey key, which contains the UILocalNotification. That should give you enough information to determine which video needs to be played, which you can do with the Media Player framework.
I am using following code for local notification. But It is not working. Location is successfully being updated and it get into these methods but notification is not being fired. Any idea?:
NOTE: It is working when the app is in background but not working when the app is closed.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)]){
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}
[[UIApplication sharedApplication] cancelAllLocalNotifications];
// Override point for customization after application launch.
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
return YES;
}
-(void) locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
if ([region isKindOfClass:[CLBeaconRegion class]]) {
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = #"You are checked in";
notification.soundName = #"Default";
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
}
You should keep in mind that notifications present only when your app in background, not at the foreground. If your are in foreground implement - application:didReceiveLocalNotification: of the AppDelegate and handle notification manually by yourself.
UPD
If your app is not running even in background, your code will not be executed. Look for Background modes (Tracking the User’s Location section) for possible solutions in order to ask system launch your app by events even currently it is not in the memory
My case was the notification was disabled from the
Settings -> Notifications -> YOUR_APP -> Allow Notifications
Local notification will work even your application removed from the background. But in your case, you are listening to the location manager event and triggering the local notification inside the delegate method. Your location manager event will not get triggered once you killed the application. So your local notification will not get triggered at all.
Wen app is closed applicationDidEnterBackground was called so put this background task code. and class the local notification.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bgTask = [application beginBackgroundTaskWithName:#"MyTask" expirationHandler:^{
// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task, preferably in chunks.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
//// just u call the method want ever u want example
[self notification];
}
- (void)notification
{
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = #"You are checked in";
notification.soundName = #"Default";
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
I think this is helpful to u.
When your app gets killed, beacon monitoring will still relaunch it — that's the great thing about beacon monitoring!
All you need to do is re-start the monitoring in the application:didFinishLaunchingWithOptions: method. If you do that, the didEnterRegion event which resulted in launch of the app will immediately get delivered to the delegate, which should trigger the notification.
Estimote has a more detailed guide:
Launching notifications in iOS when the app is killed. It uses ESTBeaconManager, ESTBeaconManagerDelegate and ESTBeaconRegion classes from the Estimote SDK, but you can simply replace these with regular Core Location classes for the same effect.
I send a LocalNotification like this:
UILocalNotification *notification = [UILocalNotification new];
notification.alertBody = #"Hello, open me";
notification.userInfo = #{#"TheKey": #"www.stackoverflow.com"};
notification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
and in AppDelegate I do use:
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
NSDictionary *userInfo = notification.userInfo;
NSURL *siteURL = [NSURL URLWithString:[userInfo objectForKey:#"TheKey"]];
[[UIApplication sharedApplication] openURL:siteURL];
}
It opens the URL in new broswer window but it takes like 5-10 seconds for the app to take that action. Is it possible to open browser immediatly when LocalNotification is opened?
On iOS 7 and prior your approach would indeed be the only one. This is because UILocalNotification is only used to open your app, i.e. call the AppDelegate's method application:didReceiveLocalNotification:. So, the first place indeed for you to perform any actions would be that method.
However, with iOS 8 interactive notifications have been introduced. These allow the user to perform a specified action without opening the app.
In the screenshot you see that the user just received a notification and now has the option to perform certain actions on it, without actually going back into the app. You can find a great tutorial on how to implement interactive notifications here!
What is the difference between presentLocalNotificationNow and scheduleLocalNotification.
For the both following function is showing notification after 1 second
-(void)showLocalNotification:(NSNotification *)notification {
NSString *msg = #"test message";
[[UIApplication sharedApplication] cancelAllLocalNotifications];
UILocalNotification *_localNotification = [[UILocalNotification alloc]init];
_localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:1];
_localNotification.timeZone = [NSTimeZone defaultTimeZone];
_localNotification.alertBody = msg;
_localNotification.soundName = UILocalNotificationDefaultSoundName;
_localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber]+1;
[[UIApplication sharedApplication] scheduleLocalNotification:_localNotification];
// or
//[[UIApplication sharedApplication] presentLocalNotificationNow:_localNotification];
}
If the application is running in the background, the local notification will not get an alert or sound, as it is directly received by the application. In that case, you need to present the notification using presentLocalNotificationNow.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
UIApplicationState applicationState = application.applicationState;
if (applicationState == UIApplicationStateBackground) {
[application presentLocalNotificationNow:notification];
}
}
From Apple Documentation:
Once you have created an instance of UILocalNotification, you schedule
it using one of two methods of the UIApplication class:
scheduleLocalNotification: or presentLocalNotificationNow:. The former
method use the fire date to schedule delivery; the latter method
presents the notification immediately, regardless of the value of
fireDate. You can cancel specific or all local notifications by
calling cancelLocalNotification: or cancelAllLocalNotifications,
respectively.
There's no difference right here, but using scheduleLocalNotification you can schedule it at whatever time you want, not only in one second.
And, of corse, nobody promises you that presentLocalNotificationNow will show one in exactly one second, not in 0.5 or 2.0 in iOS 8, for example.