Is it possible to open an app from a background task in iOS?
I want my app to run in the background, and I want it to reappear for whatever reason without user input. Is this possible?
In Android you can have a service that runs in the background, and at any time you can start an Activity, which starts the app for that activity.
I know this does not make for a good user experience. I still want to know whether it can be done.
You can create schedule a local notification with a time offset of 0 (eg show an alert immediatly). If the use taps on the notification, the app will be launched.
But otherwise, you will not be able to launch out of the background into the forground without a notification.
NSDate * theDate = [[NSDate date] dateByAddingTimeInterval:0]; //
UIApplication* app = [UIApplication sharedApplication];
NSArray * oldNotifications = [app scheduledLocalNotifications];
// Clear out the old notification before scheduling a new one.
if ([oldNotifications count] > 0)
[app cancelAllLocalNotifications];
// Create a new notification.
UILocalNotification* alarm = [[UILocalNotification alloc] init];
if (alarm)
{
alarm.fireDate = theDate;
alarm.timeZone = [NSTimeZone defaultTimeZone];
alarm.repeatInterval = 0;
alarm.soundName = #"sonar";
alarm.alertBody = #"Background task complete, tap to show app" ;
[app scheduleLocalNotification:alarm];
}
From Apples Documentation:
"Notifications are a way for an app that is suspended, is in the background, or is not running to get the user’s attention. Apps can use local notifications to display alerts, play sounds, badge the app’s icon, or a combination of the three. For example, an alarm clock app might use local notifications to play an alarm sound and display an alert to disable the alarm. When a notification is delivered to the user, the user must decide if the information warrants bringing the app back to the foreground. (If the app is already running in the foreground, local notifications are delivered quietly to the app and not to the user.)"
Related
Any possibility to reset/clear app badge without any app interactions such as opening the app or any push/local notifications. My need is, I want to reset my app badge starting off every day without even opening the app or with any notifications.
You can schedule local notification for end of day with badge count equal 0. Check this out Updating iOS badge without push notifications
I solved this problem with the help of this solution. The working code is:
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
NSCalendarUnit unitDay = NSCalendarUnitDay;
localNotification.repeatInterval = unitDay;
localNotification.fireDate = fireDate;
localNotification.applicationIconBadgeNumber = -1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
Local notification has no alertBody, so local notification will not display upfront.
If need to show alertBody then add localNotification.alertBody = #"Your notification alertBody";.
Thanks for the answer.
General problem / application background / purpose:
I have a Timer app and I would like to play a custom sound when the App is in BACKGROUND state and receives a UILocalNotification.
I utilize UILocalNotification to trigger the timer (its the only way as an App cannot run a process in the background for longer than 10 minutes).
Issues:
Is there a way to play a different UILocalNotification sound? If so how can I do it? (In other words: when the app receives the UILocalNotification the custom sound is played - which is not loud enough.. I would like to get a proper alarm sound)
This is how I set my sound when I send my UILocalNotification:
_localNotif.soundName = UILocalNotificationDefaultSoundName;
I then create the notification and post it. Once the app receives it I handle it in the following method (please read the code comments for added information):
- (void)application:(UIApplication *)application didReceiveLocalNotification: (UILocalNotification *)notification {
NSLog(#"received notification");
// Here I try to play a custom sound created in a custom object
// however the sound does NOT get played when the APP is in BACKGROUND mode (but I still see the NSLog message in console "received notification"
SoundManager* audio = [SoundManager sharedInstance];
[audio playSound:Standard];
}
Try changing your line
_localNotif.soundName = UILocalNotificationDefaultSoundName;
To something like this:
_localNotif.soundName = "customSoundFileName.customSoundFileExtension";
As it states in official docs you have to specify the filename of a sound resource in your app’s main bundle.
I have a working example that I can share with you if you need it.
Good luck!
In the view controller where you fire the local notification:
.h
#import <AVFoundation/AVFoundation.h>
#interface ViewController : UIViewController <AVAudioPlayerDelegate>
#property (nonatomic, strong) AVAudioPlayer *notificationSound;
You don't have to fire a local notification if it enters the background in the app delegate, a local notification will fire regardless if they are in the background or not. didReceiveLocalNotification is how you handle it when the app is active : From the docs here :
Sent to the delegate when a running app receives a local notification.
.m
-(void)startTimer {
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(runTimerTasks:) userInfo:nil repeats:YES];
[self fireLocalNotification];
}
-(void)fireLocalNotification {
UILocalNotification *timerDoneNotification = [[UILocalNotification alloc] init];
timerDoneNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:secondsLeft];
timerDoneNotification.alertBody = #"Time Up!";
timerDoneNotification.alertAction = #"OK";
timerDoneNotification.timeZone = [NSTimeZone defaultTimeZone];
timerDoneNotification.soundName = #"alarm.aif";
[[UIApplication sharedApplication] scheduleLocalNotification:timerDoneNotification];
}
And then if you just want to play/stop the sound elsewhere like if the secondsLeft is 0 when the app is active you call it as follows :
[self playAlarm];
-(void)playAlarm {
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *filePath = [mainBundle pathForResource:#"alarm" ofType:#"aif"];
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
NSError *error = nil;
self.notificationSound = [[AVAudioPlayer alloc] initWithData:fileData error:&error];
self.notificationSound.numberOfLoops = -1;
[self.notificationSound play];
}
And to stop it:
[self.notificationSound stop];
Downside to this is UILocalNotification sounds can not be longer than 30 seconds but it answers the question at hand.
Reference : UILocalNotification Docs
Points of interest :
When the system delivers a local notification, several things can happen, depending on the app state and the type of notification. If the app is not frontmost and visible, the system displays the alert message, badges the app, and plays a sound—whatever is specified in the notification. If the notification is an alert and the user taps the action button (or, if the device is locked, drags open the action slider), the app is woken up or launched. (If the user taps one of the custom actions you specify using the additionalActions property, the app is woken up or launched into the background.) In its application:didFinishLaunchingWithOptions: method, the app delegate can obtain the UILocalNotification object from the launch options dictionary using the UIApplicationLaunchOptionsLocalNotificationKey key. The delegate can inspect the properties of the notification and, if the notification includes custom data in its userInfo dictionary, it can access that data and process it accordingly. On the other hand, if the local notification only badges the app icon, and the user in response launches the app, the application:didFinishLaunchingWithOptions: method is called, but no UILocalNotification object is included in the options dictionary. When the user selects a custom action, the app delegate’s application:handleActionWithIdentifier:forLocalNotification:completionHandler: method is called to handle the action.
If the app is foremost and visible when the system delivers the notification, the app delegate’s application:didReceiveLocalNotification: is called to process the notification. Use the information in the provided UILocalNotification object to decide what action to take. The system does not display any alerts, badge the app’s icon, or play any sounds when the app is already frontmost.
UILocalNotification *notification = [UILocalNotification new];
notification.fireDate = [NSDate date]; //
notification.alertBody = #"This is custom alarm";
notification.soundName = #"YourCustomAudioFile.aiff";
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
BUT
Your custom audio files must conforms two conditions:
Audio length less than 30 seconds
Audio file format should be: raw PCM, or MA4, or uLaw, or aLaw (wav, aiff or caf file containers)
So if you have MP3 custom alarm sound, you should convert it...
Here is Apple documentation (lookup for Preparing Custom Alert Sounds section) link
I want to show a banner notification on the lock screen. But, while the screen is locked and off, it will not turn back on to show me the notifications.
The behavior I'm looking for is as follows:
The screen will be off, and locked. When the app gets a notification, it will turn on the screen and display a banner on the lock screen.
How can I do this?
This is automatically handled by iOS. When a notification is sent to an app, it will display the banner notification as you are looking for. In app delegate you can register notifications and handle.
UILocalNotification *notification = [[UILocalNotification alloc] init];
NSDate *fireDate = [[NSDate alloc] initWithTimeInterval:5 sinceDate:[NSDate date]];
[notification setFireDate:fireDate];
[notification setSoundName:UILocalNotificationDefaultSoundName];
NSTimeZone *timeZone = [NSTimeZone localTimeZone];
[notification setTimeZone:timeZone];
[notification setAlertBody:#"You have a new notification!"];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
This will create a new notification and fire it after 5 seconds. If the application is in the foreground, nothing will happen (unless handled in the app delegate). But if you background the application (such as shutting off the screen), you will receive a banner notification and hear the default notification sound.
If you need local notification : it means at specific time, the notification will be shown. Use UILocalNotification
If you need notification is sent from server. Here is what you need
http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1
I have the following code implemented in applicationDidEnterBackground:
-(void)applicationDidEnterBackground:(UIApplication *)application
{
// Fire date is set to 30 secs and repeat interval is set to 1 min
// for testing purpose.
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:30];
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.alertBody = #"Test Notification";
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.repeatInterval = NSMinuteCalendarUnit;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
The variable localNotification is initialised in application:didFinishLaunchingWithOptions.
All local notifications are cancelled in applicationDidBecomeActive.
Steps:
1) The app Notification Center is initially On when the app is put into background by the user hitting the HOME button.
2) Notification shows up accordingly.
3) Turn app Notification Center to Off in Settings.
4) Notification still shows up.
Notification will be not shown if the app Notification Center is turned off. Is this correct? If my assumption is wrong, how can I cancel the notification when the user turns off the app Notification Center. Deployment target is iOS5.1. iPhone is running iOS6.1.
I’m not sure I understand you, but when you pull an app out of notification center it stops showing it in the notification center window, but it’ll still show the banner or alert on the screen unless you turn that off as well.
When my iOS app exits, it registers a series of local notifications, which update the badge number at specific times. The local notifications do not bring up a popup, they simply update the badge. On my old iPod touch which does not support multitasking, this works perfectly. However, on my multitasking enabled devices, I am experiencing a very strange bug: when I have "exited" the app (i.e. it is still running in the background, but I am doing something else), the local notifications are not firing. Is there any reason why the local notifications would not fire when the app is in the background?
The code to create the local notifications runs in a loop (I create a bunch of them):
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.applicationIconBadgeNumber = totalCount; // a number generated earlier in the code
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.fireDate = endDate; // a date generated earlier
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
[localNotification release];
And also I have created the following function in my app delegate, which tells me how many notifications are set up before the app enters the background:
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(#"# Notifications: %d", [[[UIApplication sharedApplication] scheduledLocalNotifications] count]);
}
The app constantly tells me that there are 64 notifications (the number that should be set up) when it enters the background.
Check the following from Apple's developers docs:
"Each application on a device is limited to 64 scheduled local notifications. The system discards scheduled notifications in excess of this limit, keeping only the 64 notifications that will fire the soonest. Recurring notifications are treated as a single notification."
Could you problem be related to the number of notifications been scheduled?
You can find further information in http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/WhatAreRemoteNotif.html
Well #Jason you need to set the alertBody of the local notification atleast to show an alert view, thats all there is to it.
Also if you dont wont to show the view option in the alert box then set the hasAction attribute to NO.
Swift Version:
func applicationDidEnterBackground(application: UIApplication) {
let notification = UILocalNotification()
notification.alertBody = "App has been entered in background"
notification.alertAction = "open"
notification.fireDate = NSDate()
notification.soundName = UILocalNotificationDefaultSoundName
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}