performSelectorInBackground not working when App is minimized - iphone

I'm trying to keep the App running on task in background even if the User minimized and started working in other stuff on the ios device, but my method is hit only when the App is active on the screen. Am I missing something obvious here?
-(void) viewDidAppear:(BOOL)animated
{
[self performSelectorInBackground:#selector(RunMethodEvenWhenMinimized) withObject:nil];
}
-(void)RunMethodEvenWhenMinimized
{
while(YES)
{
//My Code
sleep(10);
}
}

The problem is that you seem to be confusing background processing, and NSObject's background thread helper function. You aren't actually specifying that your method should run in the background, rather, that it will run on a thread that isn't the main thread. It's recommended that you use -[UIApplication beginBackgroundTaskWithExpirationHandler:]; to notify the system that your application needs to exceed it's allotted time in the foreground for method execution. Your code will end up looking something like this when all is said and done:
-(void) viewDidAppear:(BOOL)animated
{
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
bgTask = UIBackgroundTaskInvalid;
}];
[self RunMethodEvenWhenMinimized];
[app endBackgroundTask:bgTask];
}
-(void)RunMethodEvenWhenMinimized
{
while(YES)
{
//My Code
sleep(10);
}
}

Related

Application should Active while in Background mode

I want to make my Application Active when Application is in background state, as my NStimer and other operation are performing. So, I did the following code to make my Application Active.
- (void)applicationWillResignActive:(UIApplication *)application
{
UIApplication *app = [UIApplication sharedApplication];
if (backgroundTaskBool==TRUE)
{
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task.
_locationManager.distanceFilter = 100;
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[_locationManager startMonitoringSignificantLocationChanges];
[_locationManager startUpdatingLocation];
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
});
}
}
I just wanted to know is it a correct way to do? or there will be some other way to achieve this, because this process is taking too much battery and unnecessary location updating. So please help me out from this.
Thanks in advance.
You cant run the task in back ground for longer. IOS allow you to run the background task for 10 min only (after you click home button once your app launched).
Refer this
https://stackoverflow.com/a/5326257/1545180
As your question is tagged for iOS6!
You application cannot continue to run in background unless your application requires any of these features.
Audio—The app plays audible content to the user while in the
background. (This content includes streaming audio or video content
using AirPlay.)
Location—The app keeps users informed of their
location, even while it is running in the background.
VoIP—The app
provides the ability for the user to make phone calls using an
Internet connection.
Newsstand-content—The app is a Newsstand app
that downloads and processes magazine or newspaper content in the
background.

Can we call the method after the application has been minimized?

iOS
Can we call the method after the application has been minimized?
For example, 5 seconds after was called applicationDidEnterBackground:.
I use this code, but test method don't call
- (void)test
{
printf("Test called!");
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self performSelector:#selector(test) withObject:nil afterDelay:5.0];
}
You can use the background task APIs to call a method after you've been backgrounded (as long as your task doesn't take too long - usually ~10 mins is the max allowed time).
iOS doesn't let timers fire when the app is backgrounded, so I've found that dispatching a background thread before the app is backgrounded, then putting that thread to sleep, has the same effect as a timer.
Put the following code in your app delegate's - (void)applicationWillResignActive:(UIApplication *)application method:
// Dispatch to a background queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// Tell the system that you want to start a background task
UIBackgroundTaskIdentifier taskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
// Cleanup before system kills the app
}];
// Sleep the block for 5 seconds
[NSThread sleepForTimeInterval:5.0];
// Call the method if the app is backgrounded (and not just inactive)
if (application.applicationState == UIApplicationStateBackground)
[self performSelector:#selector(test)]; // Or, you could just call [self test]; here
// Tell the system that the task has ended.
if (taskID != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:taskID];
}
});

location service in the background execution

I want to get the location of my device 24x7 times. but as per apple documentation, apps can only be run for the max 10 minutes.After that, apps is automatically killed.
I am using the below code:
- (void)applicationWillResignActive:(UIApplication *)application
{
UIApplication * app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler: ^ {
dispatch_async (dispatch_get_main_queue (), ^ {
if (bgTask != UIBackgroundTaskInvalid)
{
[app endBackgroundTask: bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
}];
// Start the long-running task and return immediately.
dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ {
lm.locationManager.distanceFilter = kCLDistanceFilterNone;
lm.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
[lm.locationManager startMonitoringSignificantLocationChanges];
[lm.locationManager startUpdatingLocation];
dispatch_async (dispatch_get_main_queue (), ^ {
if (bgTask != UIBackgroundTaskInvalid) {
[app endBackgroundTask: bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
});
}
I have also included supported Background Mode as Requires location.
But the app runs for only 10 minutes. How can i make the app to run all the time. Please help me out!
significantLocationChanges does not require you to implement the background task. just remove the bgtask creation and run it normally with the Supported Background Mode key.
Scheduled BackgroundTasks are killed by OS approx after 10 mins and hence your location service monitoring. So u only need to remove the BGTask that u are creating for location updates.

iPhone background task stops running at some point

In my iPhone app I have a background task that starts running when the app enters the background state.
The task runs fine and is structured in a loop like this:
run.
sleep for 5 min.
run.
sleep for 5 min.
etc.
For some reason, the task stops running after a certain amount of time... say half an hour to an hour.
Can anyone help me understand why?
Here is the background task code:
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(#"Application entered background state.");
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"bgCheckSwitch"] == YES) {
//UIApplication* app = [UIApplication sharedApplication];
// Request permission to run in the background. Provide an
// expiration handler in case the task runs long.
NSAssert(bgTask == UIBackgroundTaskInvalid, nil);
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
// Synchronize the cleanup call on the main thread in case
// the task actually finishes at around the same time.
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task.
[someClass doSomeThing]; //The actual method performed by the task. The looping is in the method.
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
});
}
}
A background task only runs for a period of time, then the OS kills it. This is discussed in the multitasking WWDC10 videos.

Facing error in apple multitasking code

Actually I am working for multitasking and facing error please assist me, as I need to work on background application and also in foreground application
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplication* app = [UIApplication sharedApplication];
// Request permission to run in the background. Provide an
// expiration handler in case the task runs long.
NSAssert(bgTask == UIBackgroundTaskInvalid, nil);
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
// Synchronize the cleanup call on the main thread in case
// the task actually finishes at around the same time.
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task.
// Synchronize the cleanup call on the main thread in case
// the expiration handler is fired at the same time.
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
});
}
Put in your #interface:
UIBackgroundTaskIdentifier bgTask;
(out from NDA now).
Check out the developer documentation, if you have a developer's account. We can't really answer the os4.0 question because it's under NDA, but all the information you'll need to answer that question is on that page (once logged in).