What does "UIBackgroundTaskInvalid" mean? - iphone

I'm developing iPhone app which runs in the background(iOS4), and refer "Completing a Finite Length Task in the Background" written by Apple at the following url
http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html#//apple_ref/doc/uid/TP40007072-CH5
Then I've been able to implement background tasks.
(Of course, I see that application has 10min time limitaiton.)
However, I still can't understand what "bgTask = UIBackgroundTaskInvalid;"(Line7,16 of Listing 4-2) means.
In my opinion, the line shown above has never been reached.
Because there is "endBackgroundTask:" before that and the background task will be ended.
In fact, when I checked with xcode debugger, this thought may be true and not reach at Line7, 16.
If so, is this line redundant?
Or is there any reason to have to be written?
I would appreciate any help about this.
Thanks in advance.

The code in the block is called if the 10 minutes runs out before the application has completed its background task.
The code in this block must call endBackground: to indicate the situation is acknowledged and accepted by the application - if it doesn't the application will be terminated. Note that calling the method doesn't terminate the application - it simply indicates to the OS that the background task execution has completed.
The second line is simply to reset bgTask to a neutral value, rather than leaving it set id of a task that no longer exists. It's a tidiness thing rather than being essential.
(I wouldn't be surprised if the second line isn't executed until the application is next foregrounded, since once background execution ends the app doesn't get any CPU time to run. Haven't tested this, though)

Key to understanding it is that instead of having a completionHandler you have an expirationHandler. It only executes that line as a 'clean up' of your code taking toooo long.
To clean up it has nuke/kill/end your background task. So first it has to stop it with:
[application endBackgroundTask:bgTask];
Then it also sets a flag on the task so it won't be executed again.
bgTask = UIBackgroundTaskInvalid;
The reason you see it twice in the code is because either:
It successfully runs in the background and gets finished in the dispatch block...so you need to inform the app that hey I'm done.
You don't finish in the background but the app is like times up! You gotta go...clean up after yourself by doing a [application endBackgroundTask:bgTask]; + bgTask = UIBackgroundTaskInvalid;

Related

AVAudioSession sharedInstance requestRecordPermission:^(BOOL granted)

Here is my code:
-(void) recordButton{
[[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
NSLog(#"value of the grant is :: %hhd", granted);
if (granted)
{
// perform operation recording
// perfrom some operation on UI(changing labels and all)
}
else
{
// do operation
}
}];
}
Problem is, when i run my app for the first time , after reset in the privacy and my app calls the above defined method, it creates trouble.
when My app run for the first time, allow/disallow microphones messgae(OS defined) method pops up.
when i click allow it displays the boolean(granted correclty). Goes inside IF correctly. Starts the recording correctly. but the UI freezes. and the second part of IF i.e changing label names, doesnt execute till , a timer (added by me stops the method and recording) executes.
PLease help.
I can sense that my 2nd part of the IF(changing UI label are not working in foreground), i.e. background work is working perfectly. Please Help, I am not expert. started iOS programing 2 months back.
I got the answer. my problem was, that when program reached If(granted) ,
it was performing the recording function but didn't performed on UI(changing labels and all).
The problem was, that the whole code was treated as a separate thread and was performed in background.
That's why recording was working properly(as it was a background process).
But UI(changing the labels) was a foreground task.
So For that, I had to execute the UI CODE under a thread that was on MAIN queue. And now it works perfectly.
AVAudioSession's requestRecordPermission callback is a background thread. Using code on the main thread inside a background thread causes issues (and most likely a crash).
You should call a method on the main thread to execute any post granted code. Using performSelectorOnMainThread: is an excellent way to make sure your code is running on the main thread (as explained here: execution on main thread).

Keep app in background for 10 mins while doing nothing in background

I have this code in my app -
- (void)applicationDidEnterBackground:(UIApplication *)application
{
...
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
if (bgTask != UIBackgroundTaskInvalid)
{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
}];
//NO MORE CODE AFTER THAT
}
I just want to extend my app's duration of running in background to handle some events from an external source.
By using this code the app, sometimes the app is crashing with the logs -
[app-name] has active assertions beyond permitted time
can anyone help me with this?
Even though its crashing, it wont affect the user. The user wont get to know about the crash since the app is in background. I'm just worried about rejection by the app store review. Need urgent help! :(
EDIT :
My app is communication to an external device via asynchronous TCP socket. With above code when I send my app to the background it recieves data for an additional 10 mins. After 10 minutes when I bring the app to the foreground the app hasn't closed yet, but it shows that the socket connection has disconnected. So as soon as the app comes to foreground AFTER 10 mins, it starts re-establishing the connection.
This happens in about 80% of the test cases. Remaining 20% result in the aforementioned crash.
What sort of work are you doing on the main thread whilst in the background? If you're blocking it, the expiration handler block won't be called, viz:
A handler to be called shortly before the application’s remaining
background time reaches 0. You should use this handler to clean up and
mark the end of the background task. Failure to end the task
explicitly will result in the termination of the application. The
handler is called synchronously on the main thread, thus blocking the
application’s suspension momentarily while the application is
notified.
This will cause the watchdog to maul you as having failed to terminate your background tasks in time.

ios voip app run only 10 min in background

I am creating a voip application for iPhone and iPad family in which I have done following things :
Added the UIBackgroundModes key in the plist file with values 'audio' and 'voip'.
Create NSInputStream and NSOutputStream with tag NSStreamNetworkServiceTypeVoIP and scheduled them in runloop of another thread(not main thread).
Created a background task in applicationDidEnterBackground.
Added setKeepAliveTimeout handler (timeout value 600 sec).
Application relaunches when code in handler of setKeepAliveTimeout is called.
Application relaunches if I dont put setKeepAliveTimeout handler ,but tries to send any signal to app after suspension(10 mins in background is completed).
I have tried almost everything that came in my mind, Need pointers towards the solution Thanks in advance,
It is the duty of the setKeepAliveTimeout handler to care about the connection. Thus, you should use an alive interval that is shorter than the timeout time of your connection.

how can I run iOS4 app in the background?

I'm developing an app for iOS4. The application is made of two main components, one that is supposed to run in the background and one that is constantly displayed on screen and takes data from the first one. Here's the problem: the first component works just fine until it is put in the background. At that point it stops sending data. Why is that? Is there any workaround?
Thank you.
If you're not using VoIP, Audio or GPS you can only use the task completion mode (which is limited to 10 minutes in background).
To do that you have to tell the OS you want to start a task with:
UIApplication* app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
and when you're done, you can end it with:
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
Remember that if your running longer than 10 minutes, the OS will kill your app.
In applicationDidEnterBackground: you have the problem that your code still blocks the main thread, which is why it's killed when you exit the app.
If you want to start executing code in applicationDidEnterBackground: you should begin the background task and dispatch whatever it is you want to do with dispatch_async(queue, block_with_your_code);
You can read more on it here
There is non you are only allowed to run VOIP, Audio or Locationbased apps in the background.
So unless you apps falls in one of those categories there is no way to keep you app working in the background.
Apple allows only certain types of apps to run in the background, like navigation and VOIP apps, to name just two. But even those are limited to only the necessary tasks.
The only alternative are "longrunning background tasks" - this allows an app to continue working in the background for up to ten minutes (the exact duration of this "grace period" is subject to change, afaik). You may obvserve this on apps like Hipstamatic, which will finish postproduction on images even when the app is being moved to the background.
As others have pointed out there's no real way to do this, but there is a workaround some apps use. You basically play a track from the users iPod library in the background, which enables your app to stay working in the background for a longer time. You can read more about it on Tapbots' site.

How to keep an iPhone app running on background fully operational

first of all, I know there is only support for voip, audio and location apps to run in background and that they will run just while the audio is been played or while using location services, etc.
What I want to know is if there is a way to keep my app running on background fully operational, doesn't matter the impact on battery's life.
That way the user of my app can select from settings to keep alive the app whenever he wants and just for the amount of time he wish. e.g if he is waiting for something that requires the app to be running, after receiving the messages he can turn off the keep alive functionality.
I don't know if this is possible but I had read some post that say so but unfortunately they didn't say how to =(
UPDATE: In this tutorial, I found that Acrobits has two apps on the Apple Store that "can force the application to stay alive and awake in the background". So there is a way to do this?
From ioS 7 onwards, there are newer ways for apps to run in background. Apple now recognizes that apps have to constantly download and process data constantly.
Here is the new list of all the apps which can run in background.
Apps that play audible content to the user while in the background, such as a music player app
Apps that record audio content while in the background.
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Apps that need to download and process new content regularly
Apps that receive regular updates from external accessories
You can declare app's supported background tasks in Info.plist using X Code 5+. For eg. adding UIBackgroundModes key to your app’s Info.plist file and adding a value of 'fetch' to the array allows your app to regularly download and processes small amounts of content from the network. You can do the same in the 'capabilities' tab of Application properties in XCode 5 (attaching a snapshot)
You can find more about this in Apple documentation
You can perform tasks for a limited time after your application is directed to go to the background, but only for the duration provided. Running for longer than this will cause your application to be terminated. See the "Completing a Long-Running Task in the Background" section of the iOS Application Programming Guide for how to go about this.
Others have piggybacked on playing audio in the background as a means of staying alive as a background process, but Apple will only accept such an application if the audio playback is a legitimate function. Item 2.16 on Apple's published review guidelines states:
Multitasking apps may only use
background services for their intended
purposes: VoIP, audio playback,
location, task completion, local
notifications, etc
If any background task runs more than 10 minutes,then the task will be suspended and code block specified with beginBackgroundTaskWithExpirationHandler is called to clean up the task. background remaining time can be checked with [[UIApplication sharedApplication] backgroundTimeRemaining].
Initially when the App is in foreground backgroundTimeRemaining is set to bigger value. When the app goes to background, you can see backgroundTimeRemaining value decreases from 599.XXX ( 1o minutes). once the backgroundTimeRemaining becomes ZERO, the background task will be suspended.
//1)Creating iOS Background Task
__block UIBackgroundTaskIdentifier background_task;
background_task = [application beginBackgroundTaskWithExpirationHandler:^ {
//This code block is execute when the application’s
//remaining background time reaches ZERO.
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//### background task starts
//#### background task ends
});
//2)Making background task Asynchronous
if([[UIDevice currentDevice] respondsToSelector:#selector(isMultitaskingSupported)])
{
NSLog(#"Multitasking Supported");
__block UIBackgroundTaskIdentifier background_task;
background_task = [application beginBackgroundTaskWithExpirationHandler:^ {
//Clean up code. Tell the system that we are done.
[application endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;
}];
**//Putting All together**
//To make the code block asynchronous
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//### background task starts
NSLog(#"Running in the background\n");
while(TRUE)
{
NSLog(#"Background time Remaining: %f",[[UIApplication sharedApplication] backgroundTimeRemaining]);
[NSThread sleepForTimeInterval:1]; //wait for 1 sec
}
//#### background task ends
//Clean up code. Tell the system that we are done.
[application endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;
});
}
else
{
NSLog(#"Multitasking Not Supported");
}
For running on stock iOS devices, make your app an audio player/recorder or a VOIP app, a legitimate one for submitting to the App store, or a fake one if only for your own use.
Even this won't make an app "fully operational" whatever that is, but restricted to limited APIs.
Depends what it does. If your app takes up too much memory, or makes calls to functions/classes it shouldn't, SpringBoard may terminate it. However, it will most likely be rejected by Apple, as it does not follow their 7 background uses.
May be the link will Help bcz u might have to implement the code in Appdelegate in app run in background method ..
Also consult the developer.apple.com site for application class
Here is link for runing app in background