Search code examples
iosobjective-cbackgroundlocationlte

Are there any way to upload locations from background frequently using 3G/4G/LTE?


I want to make an iOS7 devise to upload its locations to server from background using 3G/4G/LTE(NOT WiFi) frequently like less than every 5 to 10 mins or when it's location changed.

What I already have tried is like these:

1.Background Fetch

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler is called so irregularly and not controllable.

2.Remote Notification(NOT silent push)

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler is called only in WiFi connection.

3.CLLocationManager

I put uploader in - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation but it is called when on WiFi only.

I want to realize an application like "Find Your Friends" which is the Apple native application in iOS8. Are there any ideas?

Thank you for your help.

UPDATE

I tried NSURLSession upload triggered by CLLocationManager didUpdateToLocation like below, but still it uploads only on WiFi.

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{

[[NSUserDefaults standardUserDefaults] setFloat:newLocation.coordinate.latitude forKey:@"lat"];
[[NSUserDefaults standardUserDefaults] setFloat:newLocation.coordinate.longitude forKey:@"lon"];
[[NSUserDefaults standardUserDefaults] synchronize];

[self update];

}

- (void)update
{

NSURL *url = [NSURL URLWithString:@"http://.../updater.php"];
NSString *identifier = [NSDate date].description;
NSURLSessionConfiguration *configration = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier];
configuration.networkServiceType = NSURLNetworkServiceTypeBackground;
configuration.discretionary = NO;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"PUT";
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
                                                      delegate:self
                                                 delegateQueue:[NSOperationQueue mainQueue]];

float lat = [[NSUserDefaults standardUserDefaults] floatForKey:@"lat"];
float lon = [[NSUserDefaults standardUserDefaults] floatForKey:@"lon"];

NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                            [NSNumber numberWithFloat:lat], @"lat",
                            [NSNumber numberWithFloat:lon], @"lon", nil];

NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:nil];

NSString *path = [[self applicationDocumentsDirectory].path stringByAppendingPathComponent:@"json.data"];
[data writeToFile:path atomically:YES];

NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromFile:[NSURL fileURLWithPath:path]];

[task resume];

}

- (NSURL *)applicationDocumentsDirectory
{

// The directory the application uses to store the Core Data store file. This code uses a directory named "jp.skyElements.NNZ" in the application's documents directory.
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];

}

Solution

  • You have background location updates mode which allows your app to get notified about location changes. Read more on this in Background Modes section in Xcode documentation for iOS.

    Now I never tried to do any network requests during background location updates but what I would try is the following:

    NSURLSession with background configuration. POST to server and delegate all burden of this to iOS itself. QoS, network throttling, power efficiency and other benefits come out of this.