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];
}
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.