I was wondering if in iOS7, with the new API's it was finally possible to respond to a notification in the background, in my case, I have the following observer:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(storeChanged:)
name:EKEventStoreChangedNotification
object:eventStore];
I am receiving the notification perfectly but i need to run the app so that the selector gets called. I've browsed through the response and they say it's not possible but not sure if they where referring to iOS7 specifically.
Any thoughts?
Thanks!
The EKEventStoreChangedNotification will only fire when your app comes to the foreground. However if you want to call your storeChanged: method in the background, and thus having the UI already updated on coming to foreground again, you need to add the Background Fetch capability to your app.
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
In your app delegate didFinishLaunchingWithOptions method add the line
[application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
This ensures your app actually calls your background fetch, as the default interval is never. This minimum key is the key that ensures iOS handles when to call your background fetch method. You can set your own minimum interval if you don't want it to fire as often as possible.
Finally implement the background fetch method in your app delegate:
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[self storeChanged:nil];
completionHandler(UIBackgroundFetchResultNewData);
}
You can test in Xcode while debugging from Debug > Simulate Background Fetch.
Firstly when the app is in the background you can only run methods using the background task APIs to call a method after you've been backgrounded (as long as your task doesn't take too long - usually ~10 mins is the max allowed time). This applies to all versions of iOS even iOS7.
Read this question for more clarifications.
App States and Multitasking Guide by Apple can give you more clarifications on background handling.
Related
I am building an app that needs to speak data while the app is in the background (or screen is off). The speaking part is done via AVSpeechSynthesizer.
My Android app launches a service that listens for the data and whenever it needs to say something, I say it and its done. Now iOS doesn't allow these kind background tasks from what I read. The closet thing is called 'Executing Finite-Length Tasks' which looks like has a time limit of 10 mins max. So this will not work for me. Instead it looks like I need to use Push Notifications.
Looking at the documentation for Push Notifications, if I understand it correctly, if my app is in the Foreground, then my app receives the Push Notification instantly. While if my app is in the Background, a notification is set (notification center), and once the user hits the notification, my app launches with the payload.
The question here is, is there anyway to make a push notification wake my app immediately so I can speak some info?
Or what are some of the other alternative approaches that should be used in this case?
My other idea would be to implement some sort of mp3 stream per user, that would stream audio which I could play in the background. But this seems excessive for what I am trying to accomplish?
I'm not sure if you'll be able to invoke speech synthesis from the background, but you can have you app notified when the push arrives. The trick is to implement the
- (void) application: (RMApp *) application didReceiveRemoteNotification: (NSDictionary *) userInfo fetchCompletionHandler: (void (^)(UIBackgroundFetchResult result)) completionHandler
UIApplicationDelegate method (note the completionHandler parameter).
You must also set the Remote Notifications Background Mode capability.
And you must set content-available in your push notification payload.
A decent writeup on these steps found here:
http://samwize.com/2015/08/07/how-to-handle-remote-notification-with-background-mode-enabled/
I am developing an app which only works in 8.30am to 5.30pm. I want to store the data only in between 8.30am to 5.30 pm. I used local notification for doing so. But it only works when user tap the notification.In 8.30am and 5.30pm, i need to execute some code even if the app is killed. Is there any other mechanism to do so...?
Here is my code:
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (notification!=nil)
{
[self application:application didReceiveLocalNotification:notification];
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
code to be executed;
}
There is no way to execute a method in your app if the app is killed. You can bring the app up in the background using silent notifications. But silent notifications are better suited for News apps or apps which need to download content in the background so it is readily available for users when the app comes to the foreground.
Apart from this, the only way to execute the method is when it is either in the foreground or at least active in the background (using one of the available background modes). If your app is using a background mode only to stay in the background, Apple will reject the app, so be careful.
I'm developing a Calendar/Alarm app for iOS which is synchronising with a web server. When an activity is added on the server, a push notification is sent out so that the iOS client can fetch the new data and, if needed, update and schedule the time for next alarm (local notification).
But this only works when the app is open on client side. I would like the client to receive the push notifications and if needed, re-schedule the time for next alarm in background.
Is this impossible on iOS?
You can use Background Fetch for this, where the OS will "wake up" your app periodically to perform data fetching in the background.
First, enable the background fetch capability for your app. In XCode 6, view your project, then go to the Capabilities tab, turn on Background Modes, and check Background Fetch.
Then you'll have to implement some codes in the App Delegate:
In application:didFinishLaunchingWithOptions:, add:
[application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
The above sets how often you wish the system to "wake up" your app for background processes ideally. Note that the final frequency is determined by an algorithm in the iOS, so it may not always be this often.
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
//fetch code here
completionHandler(UIBackgroundFetchResultNewData);
}
The above is the actual overridden function that is called during this period of background process. Remember to call the completionHandler - failing to do so might reduce the chance of your app being run in the background next time (or so says the docs). The enums you may pass to the completionHandler are UIBackgroundFetchResultNewData, UIBackgroundFetchResultNoData, UIBackgroundFetchResultFailed. Use one of these depending on the result of your fetch.
// use this methods in Appdeleagte
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
[self showAlarm:notification.alertBody];
application.applicationIconBadgeNumber = 1;
application.applicationIconBadgeNumber = notification.applicationIconBadgeNumber-1;
}
// call this in appdelagete
-(void)makeNotificationRequest:(UILocalNotification *)notification1
{
[self showAlarm:notification1.alertBody];
}
// call this mathods in appdelagte
- (void)showAlarm:(NSString *)text {
**strong text**
// set notification and call this notification methods your another view .....
[[NSNotificationCenter defaultCenter] postNotificationName:#"uniqueNotificationName" object:self]; //leak
}
I am using badge notifications in my app and it works fine but I get the badge number by calling a method. So if method is called then the badge number gets increased but how to call that method while app is closed.
- (void)repeatedMethod {
SOWObject *object =[[SOWObject alloc]init];
[object getBadgeNumber:[self getDBPath]];
// I get badgeArray from above method
[UIApplication sharedApplication].applicationIconBadgeNumber=badgeArray.count;
}
is there any way we can call this method each day when date is changed and update badge number.
So far as I know, you can do this with 3 options:
Use Silent notification - for iOS7 and above only. a bit complicated since you need to enable Push and do back-end intergration
Use Background refresh - Create a timer + UIBackgroundTaskIdentifier. (not 100% sure)
Use Local/Push Notification - disadvantage using this, user knows of such notification is triggered.
implement this delegate method in your appdelegate:
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif
This method is fired whenever the OS finds any local notifications.(it doesn't matter whether your app is in the background or in the foreground).
For more information & code look here
Look at the accepted answer.
Edited:
Answer for you to call a method while app is in background is here
So, it basically says not all the apps have access to background execution. Officially it's mentioned in the apple's developer site also: HERE
Im a newbie to iOS. I need some guidance on which is the best way to retrieve json every 5 sec from a remote server both, when in foreground or background, so that the UI gets updated properly regardless of the state. For example: Similar to a live cricket score app for iOS.
Any leads will help me. Thanks.
You should use background fetching, a system-supplied way of efficiently polling. Think in terms of minutes to hours between each poll. Otherwise, use silent push notification: it will wake up the app to do actual downloading. Read on if you are trying to do this for an actual app that you want in the app store.
Facebook app uses this push-to-download AND also abuses this feature to poll to often, thus draining the battery. That is why most people will turn this feature off for Facebook and hence there is then NO polling at all anymore. So be careful with how much energy you consume for a real app.
For fetching data from background you can use BackgroundFectch mechanism.
All you need to do is
In appdelegate class you have to set the time interval.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];//default fetch interval is never,
return YES;
}
Enable the app for background fetch
Target->Capabilities->backgroundModes->backgroundFetch
3.Final step is implement the following method in app delegate class.
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
Hope this will help you .
There is one sample app in Gitgub in which NSXmlParser is used .You can refer that .
You should use NSTimer for repeatedly performing actions::
The following class method will help you:
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti
target:(id)aTarget
selector:(SEL)aSelector
userInfo:(id)userInfo
repeats:(BOOL)yesOrNo;
Use repeats:YES.
In iOS 7 you have a new background execution method which helps in a situation like this.
Apps that use push notifications to notify the user that new content is available can fetch the content in the background. To support this mode, include the UIBackgroundModes key with the remote-notification value in your app’s Info.plist file. You must also implement the application:didReceiveRemoteNotification:fetchCompletionHandler: method in your app delegate.
So you could send push notification from a server in a timely manner so app can be configured to do the background execution and fetching data.