I want to run a background task. for check the network connectivity even the application in background
-(void) beginBackgroundUploadTask
{
isBackGroundRunning = YES;
if(self.backgroundTask != UIBackgroundTaskInvalid)
{
[self endBackgroundUploadTask];
}
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"Background Time Remaining :%f",[[UIApplication sharedApplication] backgroundTimeRemaining]);
}];
}
-(void) endBackgroundUploadTask
{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask ];
self. backgroundTask = UIBackgroundTaskInvalid;
}
-(void) initializeUpdateTimer
{
a= 0;
[self.updateTimer invalidate];
self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:5
target:self
selector:#selector(checkNetWorkStatus)
userInfo:nil repeats:YES];
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
[[NSRunLoop currentRunLoop] addTimer:self.updateTimer forMode:NSDefaultRunLoopMode]; //NSDefaultRunLoopMode
[[NSRunLoop currentRunLoop] run];
});
}
}];
}
I am initializeUpdateTimer function when application comes to background.
The task is automatomatically stops after 3 minutes.
Is it possible to extend the time for 30 minutes.
Theres no way to check if Internet is available once your app is suspended, usually iOS suspends apps in 3 mins but it depends on the OS. But theres a hacky way
If you need to know that, is your app is awake or not try using silent push notification,
if you receive silent push set a local notification for 30 or more and if you receive another silent push notification remove local notification from its schedule,
if silent push never arrives let the local notification do its job.
its my way to implement your requirement but its never recommended, neither by me.
Related
I need to run some code when the user enters a background state. The default time I was getting for when I entered the background on iOS 9 was 10 seconds. I needed a bit more than that, so I found that this code will extend the time to 3 minutes:
- (void)extendBackgroundRunningTime {
if (_backgroundTask != UIBackgroundTaskInvalid) {
// if we are in here, that means the background task is already running.
// don't restart it.
return;
}
NSLog(#"Attempting to extend background running time");
__block Boolean self_terminate = YES;
_backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:#"DummyTask" expirationHandler:^{
NSLog(#"Background task expired by iOS");
if (self_terminate) {
[[UIApplication sharedApplication] endBackgroundTask:_backgroundTask];
_backgroundTask = UIBackgroundTaskInvalid;
}
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"Background task started");
while (true) {
NSLog(#"background time remaining: %8.2f", [UIApplication sharedApplication].backgroundTimeRemaining);
[NSThread sleepForTimeInterval:1];
}
});
}
However, my task doesn't need all of this extra time, and I would like to conserve as much battery as possible. Is there any way to use this or similar code to get 1 minute of background time, or some other value between 10 and 180 seconds?
You should call endBackgroundTask: once you are done with your background processing. If you are done before the 3 minute time allotted to you, that should end your background processing early and let iOS suspend you. I haven't tested it to verify, but that's what the docs suggest.
I have a app that fetch some content from server via REST api after every 5 mins in background using the UIBackgroundTaskIdentifier. My problem is that this works fine for 1,2 hours and then after it is expired it never re starts the background task. The code I am using is given below,
In AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIApplication* app = [UIApplication sharedApplication];
self.expirationHandler = ^{
[app endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
// self.bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];
NSLog(#"Expired");
self.jobExpired = YES;
while(self.jobExpired) {
// spin while we wait for the task to actually end.
[NSThread sleepForTimeInterval:1];
}
self.bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];
// Restart the background task so we can run forever.
[self startBackgroundTask];
};
self.bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];
[self monitorBatteryStateInBackground];
}
- (void)monitorBatteryStateInBackground
{
NSLog(#"Monitoring update");
self.background = YES;
[self startBackgroundTask];
}
- (void)startBackgroundTask
{
NSLog(#"Restarting task");
// Start the long-running task.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// When the job expires it still keeps running since we never exited it. Thus have the expiration handler
// set a flag that the job expired and use that to exit the while loop and end the task.
while(self.background && !self.jobExpired)
{
[self uploadPhotostoServer];
[NSThread sleepForTimeInterval:240.0];
}
self.jobExpired = NO;
});
}
In expired section it do come but never calls the method [self startBackgroundTask]
Any help will be much appreciated.
In my app , I am triggering many GET/POST request and handling the response. But just after initiating the request if I lock the device then on resuming the app after some seconds the response doesn`t come.Is there any way to let the request active even in the background or on the device locked state till the response comes. I went through the Background Execution Docs in iOS but that seems to be used if want to download or do something in background.Not fulfilling my scenario.
If you register a background task for each request, your app will keep running even when the device is locked, as long as a request is still active. The system only allows a maximum of 4 minutes though, so your requests mustn't take too long.
When you start a GET/POST request, do this:
__block UIBackgroundTaskIdentifier bgTask = 0;
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
}];
Then, store bgTask somewhere associated with your GET/POST request. Then when your request is complete, do this:
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
Wen app is closed applicationDidEnterBackground was called so put this background task code. put timer or cal the function what ever u want.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bgTask = [application beginBackgroundTaskWithName:#"MyTask" expirationHandler:^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0),
^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
//// just u call the method want ever u want example
[self notification];
// (or) timer
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(notification:)
userInfo:nil
repeats:YES];
}
i think is help ful to u
I am a new bee in iOS apps development. I want to create a background service in iOS. I also want to mention a particular time of the day and interval (every 2 hours) to call the service (kind of an Alarm to invoke service). When the service runs, some task should get performed independent of the state of app i.e. app can be in active or inactive state. Any example of it or a code snippet of implementation will help me implement this functionality.
Use this Code
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[Timer invalidate];
Timer = nil;
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"Background process is Start(EnterBackground)!");
__block UIBackgroundTaskIdentifier bgTask ;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
Timer = [NSTimer scheduledTimerWithTimeInterval:120.0f target:self selector:#selector(process) userInfo:nil repeats:YES];
}
I've an app which run in background, and I want to stop all location services 30 min after entering into background mode.
So in my background function, I do this :
// 1800 sec = 30 min * 60 sec.
NSDate *date30min = [[NSDate alloc] initWithTimeIntervalSinceNow:1800.0];
NSLog(#"Date30min : %#", date30min);
self.timer = [[NSTimer alloc] initWithFireDate:date30min interval:1 target:self selector:#selector(stopLocation) userInfo:nil repeats:NO];
And my stopLocation function is :
- (void)stopLocation
{
NSLog(#"[My APP] [PASS INTO stopLocation]");
[self.locationManager stopMonitoringSignificantLocationChanges];
[self.locationManager stopUpdatingLocation];
[self.locationManager stopUpdatingHeading];
}
But my timer never call the function, what's my error please ?
(My function is correctly implement into my .h and .m file, I tested this out of the background function.
Please help..
It's not a problem with forgetting to add your timer to a run loop (in this case).
NSTimer objects don't fire when your app goes into the background. So, I would use another technique if you want to do something 30 minutes after backgrounding.
For example, use a Background Task to run your stopLocation method later:
- (void)applicationDidEnterBackground:(UIApplication *)application {
__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{
NSLog(#" expiration handler!");
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 30 * 60 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
[self stopLocation];
// we're done with this task now
[application endBackgroundTask: bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
Of course, you also need to have declared this:
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
in your Info.plist file, but I assume you already figured that out.