I have been using https://github.com/Jawbone/UPPlatform_iOS_SDK for a while now
and getting the user's daily steps.
I wanted to pull data from the Jawbone API when the app is in background state.
I have followed this tutorial : http://www.devfright.com/ios-7-background-app-refresh-tutorial/
To call this method :
[UPMoveAPI getMovesWithLimit:10U completion:^(NSArray *moves, UPURLResponse *response, NSError *error) {
NSLog(#"This is not getting executed in background");
}];
The jawbone session is successfully verified and seems that my session is active.
But I get no response and the above NSLog doesn't get executed in background.
Please I have tried contacting Jawbone support, seems that they are not replying back.
Anyone experienced the same, please help.
Try below code options:
Option-1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[UPMoveAPI getMovesWithLimit:10U completion:^(NSArray *moves, UPURLResponse *response, NSError *error) {
NSLog(#"This is not getting executed in background");
}];
}
Option-2
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
bgTask = [application beginBackgroundTaskWithName:#"MyTask" expirationHandler:^{
// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
[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, preferably in chunks.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
Also note that you require to add UIBackgroundModes in info.plist
Hope this helps.
Related
I have some NSOperations that are started regularly in my application. They should complete even when the the application is put to background. For this, I'm using the beginBackgroundTaskWithExpirationHandler method.
Am I supposed to use the beginBackgroundTaskWithExpirationHandler/ endBackgroundTask: every time I start my task even if the app is not going to background? Or am I supposed the call the begin/end methods only when I detected a UIApplicationDidEnterBackgroundNotification?
Option 1: Use background task every time
/**
* This method is called regularly from a NSTimer
*/
- (void)processData
{
__block UIBackgroundTaskIdentifier operationBackgroundId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:operationBackgroundId];
operationBackgroundId = UIBackgroundTaskInvalid;
}];
NSOperation *operation = ...
[self.queue addOperation:operation];
operation.completionBlock = ^{
[[UIApplication sharedApplication] endBackgroundTask:operationBackgroundId];
operationBackgroundId = UIBackgroundTaskInvalid;
};
}
Option 2: Use background task only when the application is about to go to background
/**
* This method is called regularly from a NSTimer
*/
- (void)processData
{
NSOperation *operation = ...
[self.queue addOperation:operation];
}
- (void)applicationDidEnterBackground:(NSNotification *)notification
{
__block UIBackgroundTaskIdentifier operationBackgroundId = [[UIApplication sharedApplication] beginBackgroundTaskWithName:#"EnterBackgroundFlushTask" expirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:operationBackgroundId];
operationBackgroundId = UIBackgroundTaskInvalid;
}];
// wait for all operations to complete and then
// let UIApplication know that we are done
[[UIApplication sharedApplication] endBackgroundTask:operationBackgroundId];
}
Answering my own question. From the Apple Docs:
You do not need to wait until your app moves to the background to
designate background tasks. A more useful design is to call the
beginBackgroundTaskWithName:expirationHandler: or
beginBackgroundTaskWithExpirationHandler: method before starting a
task and call the endBackgroundTask: method as soon as you finish. You
can even follow this pattern while your app is executing in the
foreground.
Other Apple API reference:
You should call this method at times where leaving a task unfinished might be detrimental to your app’s user experience.
You can call this method at any point in your app’s execution.
Option2 is correct option.Here is code from Apple document for your reference.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bgTask = [application beginBackgroundTaskWithName:#"MyTask" expirationHandler:^{
// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
[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, preferably in chunks.
[self processData];
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
Apple developer Guide
I have added data fetching operations to NSOperationQueue .During the process, I just put the device to sleep mode and the process gets stopped. I surfed stack overflow an get some basic ideas.I need help to continue my fetching process without any interruption when device moves to sleep mode.Help appreciated !!
NSManagedObjectContext *managedObjectContext=((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext;
NSOperationQueue *downLoadQueue=((AppDelegate *)[[UIApplication sharedApplication] delegate]).downloadqueue;
//Fetch operation
if([fetchqueue count]>0)
{
Queue *queue=[fetchqueue objectAtIndex:0];
queue.status=#"INP";
[managedObjectContext performBlockAndWait:^{
NSError * error = nil;
if (![managedObjectContext save:&error]){
NSLog(#"Unresolved error while loading3");
}
}];
DownloadOperation *downloadOp=[[DownloadOperation alloc]init];
downloadOp.queue=queue;
[downLoadQueue addOperation:downloadOp];
}
}
The downLoadQueue started its execution. It is fetching data from server meanwhile the device goes to sleep and the execution stops. I don't know how to continue in this block applicationDidEnterBackground. How can I get my lengthy downloading process during sleep mode?
Also tried this one..But the operation was not resumed.
//code follows
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSOperationQueue *downLoadQueue;
downLoadQueue=((AppDelegate *)[[UIApplication sharedApplication] delegate]).downloadqueue;
[downLoadQueue waitUntilAllOperationsAreFinished];
});
}
Please suggest any ideas.
I think the only way to do this is background task. Take a look at apple docs about this. There are also a lot of answers on stackowerflow how to implemet such feature.
I think in your case you can try next code to execute NSOperations a in backgraund task:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bgTask = [application beginBackgroundTaskWithName:#"MyTask" expirationHandler:^{
// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
//Start your NSOperationQueue if it's not executing
//Lock current thread while operations are executing
[queue waitUntilAllOperationsAreFinished];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task, preferably in chunks.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
I am using AFNetwork (its base on NAFDownloadRequestOperation) and my task in downloading multiple zip files one by one from amazon bucket.
When app is in foreground every thing is working very well, but when app goes in background mode that time downloading is running for some time only and it will automatically stop. I read some blog about it in that I get that following method called before downloading will stop.
[self.operationUpdate setShouldExecuteAsBackgroundTaskWithExpirationHandler:^{
NSLog(#"downloading will stop");
}];
Problem in background mode downloading is automatically stop
What I want: If downloading is stop in background and when app again comes to foreground I need to resume downloading from that point.
I also use following code in AppDelegate but I am not understand how to resume previous downloading.
__block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^(void) {
[application endBackgroundTask:backgroundTaskIdentifier];
NSLog(#"applicationWillResignActive");
[__SERVER_INSTANCE cancellAllDownloading];
// [[YourRestClient sharedClient] cancelAllHTTPOperations];
}];
If any one have any solution please let me know, Thanks in advance.
You should use AFDownloadRequestOperation
Your request will look like
AFDownloadRequestOperation *operation = [[AFDownloadRequestOperation alloc] initWithRequest:request targetPath:path shouldResume:YES];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Successfully downloaded file to %#", path);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[operations addObject:operation];
After you restart your app, and generate the request having a same url, it will resume downloading. "shouldResume:YES" works.
So, on your background task you can recreate request to finish download
__block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^(void) {
[application endBackgroundTask:backgroundTaskIdentifier];
NSLog(#"applicationWillResignActive");
[__SERVER_INSTANCE cancellAllDownloading];
// recreate here your request to finish fownload,
//or recreate in when app will enter foreground
}];
Hope this helps
The background downloading stops because after sometime because you might not have enable Background Fetch in Capabilities in xcode.
Please see attached screenshot
And Appdelegate You have write this code,
-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return true;
}
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
completionHandler(UIBackgroundFetchResultNewData);
}
OR
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
NSTimeInterval ti = [[UIApplication sharedApplication]backgroundTimeRemaining];
NSLog(#"backgroundTimeRemaining: %f", ti);
// just for debug
}];
}
Hope this will help!
I am trying to get my app to continue uploading to Dropbox once it's put into the background, but I can't seem to figure out why it doesn't work.
Apple's docs give 2 ways to do this which I understand as:
1. Do something within a given time frame
2. Do one of our pre-ordained activities
Given that the Dropbox API doesn't expose an NSURLSession and Apple's closest explanation in the docs is geared towards "downloading" in the background, I assumed that the correct way is to go for approach 1, so I wrapped my code in the block Apple suggested, but once I close the app it stops.
__block UIBackgroundTaskIdentifier bgTask = UIBackgroundTaskInvalid;
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:#"UploadImages" expirationHandler:^{
// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
[[UIApplication sharedApplication] 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, preferably in chunks.
for (PHAsset *currentImage in images) {
[self.imageManager requestImageDataForAsset:currentImage options:opts resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
// set some variables...and then call Dropbox upload
[self.restClient uploadFile:fileName toPath:destPath withParentRev:nil fromPath:filePath];
}
}
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
I've also requested that the app allows network activity. It doesn't seem to make a difference
I'm pretty new to iOS so any guidance would be helpful. Maybe I'm missing something obvious.
I am using AFNetworking 2.0 for my project. It's simple that I just
send some request to the server and the server return some JSON for
me.
For testing it, I marked some debug mark in success block of
AFNetworking POST method. The problem is when the app is in the
foreground and when the app receive the response from the server,
xCode can stop at the debug marks in the success and failure block.
But when I make the request then bring the app to background (press
Home button), the debug never go into the blocks.
It seems like that they paused when the app is in background, because
when the app is in foreground again, the debug immediately go into
the block and I got the response.
Am I missing something? Cause I want the app to receive the response and do some stuffs even if it's in the background.
Here's what I use in my app:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = /*generate the parameters*/;
NSURL *filePath = [NSURL fileURLWithPath:#"imageName.png"];
[manager POST:#"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:filePath name:#"image" error:nil];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %#", responseObject);
//debug here
//Told the app to stop the Loading View, save response to DB
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
//debug here
//Told the app to stop the Loading View and try again sometimes
}];
It's my bad. I forgot to tell the app to keep running when it enter background. I added these codes into my project:
UIBackgroundTaskIdentifier backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:backgroundTask];
}];
And when the app go into background:
[[UIApplicatioz sharedApplication] endBackgroundTask:backgroundTask];
define UIBackgroundTaskIdentifier at the top of your Appdelegate.m file
UIBackgroundTaskIdentifier bgTask = 0;
and then in your
(void)applicationDidEnterBackground:(UIApplication *)application
function add the code below
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
bgTask = UIBackgroundTaskInvalid;
}];
it should be seen like :
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
bgTask = UIBackgroundTaskInvalid;
}];
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}