How to handle network in background State - iphone

I am sending email using SMTP Implementation .Now i am switching to another app network to be suspend. How to handle network not to be suspended.
Regards,
Arunkumar.P

Login to iOS Dev Center, and search "background task", you'll find the document you need.
To be more clear, every time your app is to start a task that may take some time to finish and should be alive even in the background, you should declare a UIBackgroundTaskIdentifier before such a task starts, and tell the iOS that this is the task that needs to run in the background. And you also have to make sure that when your task ends, you should always tell iOS that it's finished and no more special background permission is needed.
Your code should look like this:
//right before your critical task starts
UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;
newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
//immediately after your critical task finishes
if (newTaskId != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask: newTaskId];
}

Related

Network disconnect issue when iOS screen locks

In iOS 5 When Application Enter background wi-fi connection is lost.
But I want to use wi-fi connection for the next 4-5 minutes before the device sleeps as some tasks can be performed within 4-5 minutes of application enter background.
I think this can be accomplished by using beginBackgroundTaskWithExpirationHandler:, but i am not able to solve the problem
just disable iPhone to go to sleep mode
-(void) sleepModeDisable{
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
}
call this function every 10 second, this might help u
The way I handle this is to use beginBackgroundTaskWithExpirationHandler for every network request I'm sending.
This way I make sure that all my networking will completed even if my app moved to background.
I'm usually using one singleton object to handle all network request, so before the request is sent I call
- (void)startBackgroundTask
{
// ask for extra time if this is called when app go to suspended
UIApplication *application = [UIApplication sharedApplication];
_bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
// Clean up any unfinished task business by marking where you.
// stopped or ending the task outright.
[application endBackgroundTask:_bgTask];
_bgTask = UIBackgroundTaskInvalid;
}];
}
And after I get a response (success/failure) or if I canceled the request, I call
- (void)stopBackgroudTask
{
UIApplication *app = [UIApplication sharedApplication];
if (_bgTask != UIBackgroundTaskInvalid) {
[app endBackgroundTask:_bgTask];
_bgTask = UIBackgroundTaskInvalid;
}
}
* Don't forget to define UIBackgroundTaskIdentifier *_bgTask;
Also if you are planning to make a massive use of Wi-Fi you should set the Application uses Wi-Fi key in your plist file to YES, otherwise your Wi-Fi will be shut done after 30 minutes even if your app is running.
No rocket science here, this is intended behavior in iOS that to save battery the Wi-Fi shuts off when phone is locked UNLESS you tell iOS that your app needs a persistant Wi-Fi, then it wont close it for you when your app is running.
For that just add UIRequiresPersistentWiFi to your info.plist and mark it YES
Documentation

How to know if a task is executing in background

In my app I'm downloading lots of images on a method.
I'm using a
downloadTask = [[UIApplication sharedApplication]
beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:downloadTask];
downloadTask = UIBackgroundTaskInvalid;
}];
This is working fine, if I press the home or sleep button, the images continue downloading.
I'm showing the progress in a UIProgressView inside an UIAlertView, and when the percent is 100% the alertView is dissmised and I change the viewController to other where I show the donwloaded images.
But I only want this to happen if the app is really active at the moment the download finish.
I have been looking at the app state and while it's downloading with the screen off.
[UIApplication sharedApplication].applicationState
the state is UIApplicationStateActive during all the donwload
How can I can know if the downloading is happening with the screen off or on?
EDITED AFTER ACCEPTING THE ANSWER:
I just discovered, if I tap the home button, the app enters in UIApplicationStateBackground, if I tap the wake/sleep it enters in UIApplicationStateInactive
Following the approach of the correct answer, my app contines donwloading in both cases.
The screen is off in two states (apart from when the app has not been even opened):
suspended : in this case you don't have to worry because the download won't procede until the app gets active again; It will enter this state on
background : it's in this state for a limited amount of time before going in suspend, and the screen is already off in this moment. Here you may want to check then whether to do all the things you said or not, because in this state code can be still executed. In this state the app status is UIApplicationStateBackground, so you could just perform a check like this:
You probably want to check whether the app is in background execution in order to achieve the result. Just like this:
if([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground) {
// Do stuff
}
If it's in background, so the screen is off.
UPDATE: after few test, what I figured out is that the behaviour you are expieriencing is probably due to the execution of the download on the main thread.
You should send the download on (for instance) the global queue. This way the application will enter the background state as expected:
....
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:self.bti];
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self doBackgroundStuff];
});
....
This way, if the app is put on background while the download is in progress, the application state will turn into UIApplicationStateBackground, and then you can check it as I wrote initially. If you are doing UI updates during the progress remember to send them back to the main thread (because the download is now on a different one).
You can check whether your app is running in the background or not by setting a flag in the designated application delegate methodsapplicationDidEnterBackground: and applicationWillEnterForeground:. Example:
- (void)applicationDidEnterBackground:(UIApplication *)application
_applicationRunsInForeground = NO;
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
_applicationRunsInForeground = YES;
}
If you don't want to have this _applicationRunsInForeground flag inside your application delegate, you could observe the delegate's NSNotifications in your viewcontroller class instead (UIApplicationWillEnterForegroundNotification and UIApplicationDidEnterBackgroundNotification).

Force app to close and run in background

we have an app that has a specific purpose where an exit is required. After the exit a process needs to run in the background for a certain amount of time or until finished. We just need to know how to programmatically force the app to enter the background where processes can continue running. Any help on this would be great! Thanks in advance!
UPDATE: We have confirmed that there does not seem to be a programmatic way to force the app to quit / enter background and continue running background tasks. You can force the the app to exit using exit(0); but this kills the app all together. However, the bulk of this question was concerning running tasks in the background. We have found a solution that allows our app to begin processing data and handling tasks that a user has setup to be processed. Here is the code required. This needs to be added to the app delegate and multitasking is required on the device / IOS.
- (void)applicationDidEnterBackground:(UIApplication *)app{
// Check that IOS supports multitasking
if ([[UIDevice currentDevice] respondsToSelector:#selector(isMultitaskingSupported)]){
// Check that the device supports multitasking
if ([[UIDevice currentDevice] isMultitaskingSupported]) {
// Custom setting to allow users the freedom to enable or disable background tasks
BOOL enabled = [[NSUserDefaults standardUserDefaults] boolForKey:#"backgroundTasksEnabled_key"];
if ( enabled ){
//Get the shared application instance
backGroundApp = [UIApplication sharedApplication];
background_task = [backGroundApp beginBackgroundTaskWithExpirationHandler: ^ {
[backGroundApp endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;
}];
// Run in background
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"\n\nProcess background tasks!\n\n");
// Do your work here
});
}
}
}
}
You can force an iOS app into the background by sending a registered URL to another app to handle, such as a web site URL to Safari.
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: myWebsiteURL ]];
Many many apps that call Safari to handle URLs are approved by Apple.
To get any time in the background, an app has to be appropriately configured using one of the allowed background modes (audio, location or VOIP); or the app can request a few minutes of extra time in the background before being suspended by calling the beginBackgroundTaskWithExpirationHandler method
You can't have a process running (doing work) in the background in iOS, you get a few seconds when the app quits to do any clean up and that's it!
You cannot force an application into the background, I'm fairly sure that Apple's guidelines prohibit you from doing that. What could your app possibly be doing that it can only do in the background and not in the foreground?

Background downloading even if the phone gets locked

I am trying to implement an application for iPhone that should simply download some content out of the web. This download is quite big, so I implemented the download as a background task to give the user the chance to do some other stuff with his phone while downloading. My problem is that if the user pushes the lock button (or if auto lock kicks in) the applicationWillResignActive: in the AppDelegate is called and after about ten seconds the download is aborted because the phone does not enter background and just stays inactive.
My question is what am I doing wrong? How can I ensure that the download is continued, even if the phone is locked?
Thanks in advance.
You need to surround the downloading code with background task block like this:
UIApplication* app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
//here you need to finish what you are doing evven if you've not finished yet, otherwise your app will be killed
[app endBackgroundTask:bgTask];
}];
//here comes your downloading code
[app endBackgroundTask:bgTask];
This will give you 10 minutes(according to some other posts) to execute code in background...

iPhone AVPlayer - Execute Code in Background

I am trying to stream a remote mp3 using AVPlayer.
I have set up the Audio Session, and added the Plays Audio In Background to my info.plist file.
I am running this code:
self.timeObserver = [self->player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:nil usingBlock:^(CMTime time) {
[self updateControls];
}];
to add a time observer, that calls updateControls every second.
Thing is, when the sound buffer is low, the player just pauses, and this code in the background is stopped, so I have to manually press play in the app again. (and if I pause the player, this code doesn't run either)
Am I doing anything wrong? How can I run a piece of code the whole time in the background without interruptions?
You can't run arbitrary code in the background indefinitely. You can keep the audio playing, but you shouldn't be expecting to update your UI if you're not the frontmost app. You can update the UI when your app moves back into the foreground.
As long as you set your AVAudioSession properly and make it active, and you have the UIBackgroundModes set, you should be good to go on the audio front.
see http://developer.apple.com/library/iOS/#documentation/Audio/Conceptual/AudioSessionProgrammingGuide/Configuration/Configuration.html
You will need to envelope your background code like this:
__block UIBackgroundTaskIdentifier bgTask = nil;
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void) {
[[UIApplication sharedApplication] endBackgroundTask: bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
//Your bg code here
[[UIApplication sharedApplication] endBackgroundTask: bgTask];
bgTask = UIBackgroundTaskInvalid;