0

I want's to upload big file(video) from my application while application is in Background mode. I am using AFNetworking Library. Application is running from 3 min but after that it kill all the activity.

Below code i use in application.

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];

AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {} failure:^(AFHTTPRequestOperation *operation, NSError *error) {}];

[operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
                                            long long totalBytesWritten,
                                            long long totalBytesExpectedToWrite) {}];

[operation setShouldExecuteAsBackgroundTaskWithExpirationHandler:^{}];

[manager.operationQueue addOperation:operation];
Piotr
  • 5,543
  • 1
  • 31
  • 37
Bhavesh Patel
  • 596
  • 4
  • 17
  • Show the code you have – Wain Jun 22 '15 at 06:41
  • Finally i resolve problem. we need to update location accuracy on every 60 seconds when we trying to upload big file to server and app is in background state. By which application is not goes in suspended state and we can upload file to server after completed file upload need to stop location update timer. – Bhavesh Patel Aug 17 '16 at 14:07

2 Answers2

0

For uploading large files you have to use AFURLSessionManager class and configure its object with NSURLSessionConfiguration.

Your code to upload large file using AFNetworking would be as following:

NSString *appID = [[NSBundle mainBundle] bundleIdentifier];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:appID];

[manager setTaskDidSendBodyDataBlock:^(NSURLSession *session,NSURLSessionTask *task ,int64_t bytesSent, int64_t totalBytesSent,int64_t totalBytesExpectedToSend){
    CGFloat progress = ((CGFloat)totalBytesSent / (CGFloat)sensize);

   NSLog(@"Uploading files %lld  -- > %lld",totalBytesSent,totalBytesExpectedToSend);
    [self.delegate showingProgress:progress forIndex:ind];
}];


dataTask = [manager uploadTaskWithStreamedRequest:request progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (error) {
        NSLog(@"Error: %@", error);
    } 
    else {

    }

   }];

You also have set the value of the NSURLSessionConfiguration object’s sessionSendsLaunchEvents property to YES and implement application:handleEventsForBackgroundURLSession:completionHandler: in your app delegate class so that when your file will be uploaded completely then the system will its call this delegate method to wake up your app. So you can know that the upload process is done and can perform any further task.

You can get better idea about using NSURLSession and NSURLSessionConfiguration to download and upload files while the app is in background from below 2 links so please refer these links to implement it.

https://developer.apple.com/library/prerelease/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

http://w3facility.org/question/how-to-work-with-large-file-uploads-in-ios/

sajgan2015
  • 305
  • 3
  • 10
  • Hi! Is there any time limit with this approach? I would like to understand which is the best solution between this one and the approach that use the method `beginBackgroundTaskWithExpirationHandler`. The second one give "only" 180 seconds of extra time. – Zeb Jan 14 '16 at 16:16
  • Using beginBackgroundTaskWithExpirationHandler: is better approach while we are uploading or download large file in the background mode. – sajgan2015 Jan 15 '16 at 10:07
  • Ok but Has it a time limit or brings it to completion? – Zeb Jan 15 '16 at 10:37
  • 1
    No there is no specific time limit. You need inform the system by calling endBackgroundTask: and then system can suspend your app from background mode. Actually beginBackgroundTaskWithExpirationHandler: asks iOS to give more time to complete your task so that your app is not suspended by iOS. – sajgan2015 Jan 15 '16 at 13:36
0

Finally i resolve my problem using below code. Put below cod in applicationDidEnterBackground. after file is uploading finish you need to stop location update and timer.

if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) { //Check if our iOS version supports multitasking I.E iOS 4
        if ([[UIDevice currentDevice] isMultitaskingSupported]) { //Check if device supports mulitasking
            UIApplication *application = [UIApplication sharedApplication]; //Get the shared application instance

            __block UIBackgroundTaskIdentifier background_task; //Create a task object

            background_task = [application beginBackgroundTaskWithExpirationHandler: ^ {
                [application endBackgroundTask: background_task]; //Tell the system that we are done with the tasks
                background_task = UIBackgroundTaskInvalid; //Set the task to be invalid

                //System will be shutting down the app at any point in time now
            }];

            //Background tasks require you to use asyncrous tasks

            if (videoManager.isUploading)
            {
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    //Perform your tasks that your application requires

                    /*[application endBackgroundTask: background_task]; //End the task so the system knows that you are done with what you need to perform
                     background_task = UIBackgroundTaskInvalid; //Invalidate the background_task*/

                    if (self.locManager != nil)
                    {
                        [self.locManager stopUpdatingLocation];
                        [self.locManager stopMonitoringSignificantLocationChanges];
                    }

                    self.locManager = [[CLLocationManager alloc] init];
                    self.locManager.desiredAccuracy = kCLLocationAccuracyKilometer;
                    if (IS_OS_8_OR_LATER)
                    {
                        if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined)
                        {
                            [self.locManager requestAlwaysAuthorization];
                        }
                    }
                    self.locManager.delegate = self;
                    [self.locManager setDistanceFilter:1000];
                    self.locManager.pausesLocationUpdatesAutomatically = NO;
                    [self.locManager startMonitoringSignificantLocationChanges];
                    [self.locManager startUpdatingLocation];
                });

                if (![timer isValid])
                {
                    timer = [NSTimer scheduledTimerWithTimeInterval:60
                                                             target:self
                                                           selector:@selector(changeAccuracy)
                                                           userInfo:nil
                                                            repeats:YES];
                }

            }
            else
            {
                [self.locManager stopUpdatingLocation];
                [self.locManager stopMonitoringSignificantLocationChanges];
                fromBackGround = false;
                self.locManager.activityType = CLActivityTypeAutomotiveNavigation;
                [self.locManager setDesiredAccuracy:kCLLocationAccuracyBest];
                [self.locManager setDistanceFilter:kCLDistanceFilterNone];
                self.locManager.pausesLocationUpdatesAutomatically = NO;


                [self.locManager startUpdatingLocation];
            }
        }
    }

- (void) changeAccuracy{
[self.locManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locManager setDistanceFilter:900];}
Bhavesh Patel
  • 596
  • 4
  • 17