iOS8 : running in the background for forever : GameCenter - ios

I know this may seem a duplicate subject but its not (hopefully its not)
We have an application that uses GameCenter in the background for backend communication, up until ios8, GameCenter has ran in the background fine.
Now I need to find a fix around this, the key is that the app needs to constantly run in the background, it uses GameCenter chat server etc, so we have enabled Audio. I can't see us being able to use VOIP as an option (Apple would probably reject it)
I tried
[self performSelectorOnMainThread:#selector(keepAlive) withObject:nil waitUntilDone:YES];
[application setKeepAliveTimeout:600 handler: ^{
[self performSelectorOnMainThread:#selector(keepAlive) withObject:nil waitUntilDone:YES];
//[[GCHelper sharedInstance] applicationWentBackground];
}];
- (void)keepAlive {
self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"Background handler called. Not running background tasks anymore.");
// [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
// self.bgTask = UIBackgroundTaskInvalid;
[self keepAlive];
}];
}
Which keeps it going for a bit, I guess the main question is, is it even possible now?
I have also followed this guide
http://blog.dkaminsky.info/2013/01/27/keep-your-ios-app-running-in-background-forever/

As long as the app itself is in the foreground, you can fire a notification every xx seconds which handles the background tasks.
When the full app goes into background, you only have a limited amount of time to close actions.

Related

Long running background task in iOS

I know this is a very common question. I have read many answer but not found out the appropriate answer for me. That's why I post this question and hope someone will show me how to fix my code.
I have function startUpdate to update location using CLLocationManager. In applicationDidEnterBackground method, I write something like below:
[self startUpdate]; // position1
NSLog(#"applicationDidEnterBackground");
__block UIBackgroundTaskIdentifier bgTask;
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
[self startUpdate]; // position2
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self startUpdate]; // position3
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://google.com"]];
});
I tried to put [self startUpdate] at one of three positions (position1, 2, 3) and sometime it works, sometime not, and I do not know why.
In case it works, updating just run in 3 minutes event. If I call startUpdate when app is in foreground, then put app to background, updating will last 15 minutes with real device, and more than 1hour with simulator ( I don't know exactly, after 1 hour, i thought it would last forever then I stop testing). So what is different between: startupdate in foreground-> go to background vs startupdate in background; simulator vs real device?
right after position3, I called following line to open safari
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://google.com"]];
But it does not work. So what types of task can be executed here, in background?
I need to keep a service running forever. Some search results say that it's impossible. But some familiar apps did that (Facebook,... keeps service to receive notifications). How can they do that?
Thank you so much,
The exact behaviour of location services has been clarified in the latest update to the Core Location documentation. It now states -
The standard location service delivers events normally while an app is
running in the foreground. When your app is in the background, this
service delivers events only when the location-updates background mode
is enabled for the app. This service does not relaunch iOS apps that
have been terminated.
The significant location change service delivers events normally while
an app is running in the foreground or background. For a terminated
iOS app, this service relaunches the app to deliver events. Use of
this service requires “Always” authorization from the user.
So, it seems that for the best chance of continuing to receive location updates in the background you should switch to significant location change monitoring once you move to the background state and restore full location monitoring once you return to the foreground.

Multipeer connectivity disconnects on background

So, my ideal scenario is that I want my MCNearbyServiceAdvertiser and MCNearbyServiceBrowser to work in the background. But I understand that these need to be killed when application resign active, and resume the work when i come back to foreground.
But what is bugging me is that, when i CONNECT two peers to a session, and start chatting between them, it suddenly disconnects. Meaning.. my MCSession object disconnects when it goes to background. I was also told of the Apple bug with certificateHandler(YES);, and i explicitly call it now.
I want to set this up exactly how FIRECHAT does it. Can anyone give me some pointers on why its keeps failing, or how you guys manage to keep this active?
Thanks,
In order to for your peers to stay connected you need to start a background task when the app enters the background, otherwise iOS will tear down the network connections and suspend the app.
- (void)applicationDidEnterBackground:(UIApplication *)application {
//Start a background task to keep the app running in the background
self.bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
//If your background task takes too long, this block of code will execute
[self cleanUp];
self.bgTask = UIBackgroundTaskInvalid;
}];
//Do the work you need to do
dispatch_async(dispatch_get_main_queue(), ^{
//Finish up the transfer of data between peers
[self cleanUp];
//End the background task so that iOS doesn't kill the app
[application endBackgroundTask:_bgTask];
});
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[application endBackgroundTask:_bgTask];
}
- (void)cleanUp {
//Clean up the Multipeer session
}
Note that this only applies to existing connections that have been made while the app was in the foreground. You still have to stop the browsing and advertising when entering background.

Executing Interval output on background IOS 7

Ok , im not getting answers about this. :(
Multipeer Connectivity audio streaming stop work on background
What about this?
i'm trying to run this code on background.
- (void)applicationDidEnterBackground:(UIApplication *)application {
__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSTimer *aTimer = [NSTimer timerWithTimeInterval:3
target:self
selector:#selector(showInformation)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop]
addTimer:aTimer
forMode:NSDefaultRunLoopMode];
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
Obviously i ihave this function defined on the same scope
- (void) showInformation {
NSLog(#"showInformation is called.");
}
But when i put the app on background, the interval message, stop work and when i come back to the foreground continue working ........
This means is not running on the background?.
Is this possible? or am I trying to do something stupidly impossible?
I really appreciate some help.
Thanks a lot.
Regardless your code works or not, your background task will be terminated after a while (>10 minutes) by iOS unless the UIBackgroundModes is set in your app (VOIP, Location service, Audio ..).
For more about Background Execution check Background Execution and Multitasking.
Another option in iOS7 is using Background Fetch, but you don't have control over time (there is a smart Timer used by the iOS).
For better understanding check Raywenderlich's Background Modes in iOS Tutorial.
And if you need something working check the below SO posts:
How do I get a background location update every n minutes in my iOS application?
Running iOS App in background for more than 10 minutes
Will iOS launch my app into the background if it was force-quit by the user?

How can I run an iOS voip app in the background without external signaling?

I'm developing a voip app for iPad. I know there are similar questions, but none of the offered solutions have worked so far. I already know that I have to set the voip flag in the info.plist file (I used xcode for that). I have also set the "application does not run in the background" to "no" (who made up that name?!?). I also configured the socket as voip using the following two lines:
CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
I read through the documentation and countless posts on SO and other forums, and there seem to be a few ways to get an app to run in the background forever. I have tried the following:
Start a long running background task, and restart the task when it fires. It was explained here on SO somewhere, but I can't find the post anymore so here is the pseudocode:
expirationHandler = ^{
if (inBackground) {
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:expirationHandler];
}
};
inBackground = true;
bgTask = UIBackgroundTaskInvalid;
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:expirationHandler];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// inform others to stop tasks, if you like
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyApplicationEntersBackground" object:self];
inBackground = true;
while (inBackground) {
//send a keep alive to my server
sleep(5);
}
});
The second thing I tried was to use setKeepAliveTimeout like this:
[[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{
//send a keep alive to my server
}];
The first one seems to work very well (note that battery life and app-store approval are of no concern to me), but only when the application runs from xcode. When I put the app on the device and run it without debugger, the app stays alive for about 3 minutes and then it dies.
The second one seems to be how it is supposed to be, but my problem with it is that it has a minimum time of ten minutes. My server closes the connection after ten minutes of inactivity and setKeepAliveTimeout seems to be a bit inaccurate, so sometimes it is off by half a second or so (I've experienced 2 seconds one time). This means that once every ten minutes there is a chance that my session to the server is closed.
I use a protocol called XIMSS, used by the Communigate Pro server platform. Most voip apps seem to use SIP, which can send keep alive packets from the server, but that is not a option for me. So how can I make sure my app always wakes in time to send a keep alive? Is there anything that has an interval smaller than ten minutes?

Running a long process in the background in iOS5 and above

I have have an download queue running using ASIHTTP request. When the user presses the home screen and the app goes into the background I would like this operation to continue. I know that ASIHTTP request can run in the background, but I want the process that runs the ASIHTTP request to run in background as well.
How do i do it?
I saw this post in StackOverflow: Continuing a long running process in the background under iOS4
But the solution is in iOS4. I would like to do it in iOS5 and above..
The solution given:
UIApplication *app = [UIApplication sharedApplication];
if ([app respondsToSelector:#selector(beginBackgroundTaskWithExpirationHandler:)]) {
backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
if (backgroundTaskIdentifier != UIBackgroundTaskInvalid)
{
// you took too long - clean up what you can, then …
[app endBackgroundTask:backgroundTaskIdentifier];
backgroundTaskIdentifier = UIBackgroundTaskInvalid;
}
});
}];
}
Another question is where should I put this code.
Need some guidance on this..
The solution you found in the other answer is good for iOS 4.0 and above. It works just fine, and remains the recommended way to perform an extended task when moving to the background.
Also, unless you're trying to support iOS 3.x -- which isn't all that advisable anymore -- you don't need the respondsToSelector check.

Resources