IOS 7 Backgrounds - not for app store (rules not apply)

For generosity, I am not interested in GPS or audio file modes, since the former uses too much of the battery, and the latter does not allow any other sound to be used, otherwise it encounters an interruption in sound, which leads to the completion of background processes. I need a way of continuous processing in the background, so often there are background modes that run sometimes.

If there is some way to run the application in the background, even ignoring Apple rules, I'm interested in trying it. If the answer is VOIP, I'm not sure where to start the implementation, since all my research came out too high or as a failure. How my application will be able to work in the background using the VOIP background mode. Without any added code, the application refuses to run in the background.


I know that with iOS 7 the background modes have changed again. I would like to be able to run my application (which should never be approved in the iOS app store) in the background. I would also like to be able to stop execution in the background until a certain time in the future.

For example, I would like him to start the process for 15 minutes, plan the next task, and then sleep until that time. At the moment, I had to run a quiet track in the background for background processing, but I would like the application to really sleep during this time - also, playing real music or making a phone call are “convenient features” of the iPhone, and I don’t I love to lose them.

I know that there is GPS, but it consumes a huge amount of battery. Other background modes do not seem to give full control of background processing and application synchronization and leave most of the time and execution time for the OS.

I need my application process to run in the background for several minutes, and then sleep until a certain period of time and continue processing. Is this possible with a better approach than currently?

I saw that VOIP used to be an opportunity, but I'm not sure that it will work, because I do not need the application to run one simple task in the background, but to continue what was launched in the foreground before the application is clicked in the background. In addition, individual tasks can take up to 1 hour to complete, so they cannot be rescheduled when the background task expires. All my assumptions are based on this stream .

+6
source share
5 answers

Change This method seems to be scary coming down. By chance, recursion will seem unsuccessful for some reason (maybe a system timeout on execution?). If I put a recursion before completing the background task, the OS kills my application, but if I put it, it sometimes seems to stop the background tasks at some point. I saw him stop in the middle of my “allotted background time”.

In short, the method below works endlessly, but not endlessly. Is there a way to make guaranteed runtime infinite or another solution?


It seems that using VOIP was easier than I thought.

All that is required to run my application indefinitely (unfortunately, sleep is not an option) is to add voip to the selected background modes, either in plist or in Target Capabilities. After that, adding and running this code once, in an object that is never freed (your AppDelegate works fine here), this will allow endless processing time for background processing:

 - (void)infiniteBackgroundLoop { __block UIApplication *applicationBlockReference = [UIApplication sharedApplication]; __block AppDelegate *appDelegateBlockReference = self; __block UIBackgroundTaskIdentifier backgroundTask = [applicationBlockReference beginBackgroundTaskWithExpirationHandler:^ { [applicationBlockReference endBackgroundTask:backgroundTask]; backgroundTask = UIBackgroundTaskInvalid; [appDelegateBlockReference infiniteBackgroundLoop]; }]; } 

To allow endless sleep, add a break to the recursion.

+2
source

We also played with background modes in our application, and I check all the solutions found and I can say that there is only one way to stay active in the background and not "VOIP", because "VOIP" gives your window an awakening - every 5- 6 minutes, not infinity.

In the documentation on setKeepAliveTimeout:handler: you can see that this method will call the handler block at least every 600 seconds, and the block has a maximum of 10 seconds to complete any necessary tasks and exit.

To clear this, you can add NSLog(@"time remain: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]); in its implementation of infiniteBackgroundLoop . Because the second and next call beginBackgroundTaskWithExpirationHandler do not get the same background start time as the first call.

Another working way is the Location Manager, yes, this is bad, because use a lot of battery, but you get what you want - the application stops stopping.

The implementation can be easily found there.

-1
source

I used background extraction to achieve something similar. You can use this to keep your application active in the background.

Xcode target capabilities

-1
source

I have a demo, see if it helps you:

Add these properties to your .h file -

 @property (nonatomic, strong) NSTimer *updateTimer; @property (nonatomic) UIBackgroundTaskIdentifier backgroundTask; 

Now suppose you have an action on a button → btnStartClicked, then your method will look like this:

 -(IBAction)btnStartClicked:(UIButton *)sender { self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(calculateNextNumber) userInfo:nil repeats:YES]; self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ NSLog(@"Background handler called. Not running background tasks anymore."); [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask]; self.backgroundTask = UIBackgroundTaskInvalid; }]; } -(void)calculateNextNumber{ @autoreleasepool { // this will be executed no matter app is in foreground or background } } 

and if you need to stop this method,

 - (IBAction)btnStopClicked:(UIButton *)sender { [self.updateTimer invalidate]; self.updateTimer = nil; if (self.backgroundTask != UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask]; self.backgroundTask = UIBackgroundTaskInvalid; } i = 0; } 
-1
source

You can use the background selection and set the refresh rate for the short NSTimeInterval.

In your doneFinishLaunchingWithOptions: file, try adding:

 [[UIApplication sharedApplication] setMinimumBackgroundFetch:1]; 

I have not tested this, let me know if this could be a starting point.

-1
source

All Articles