iOS 9如何获取位置,即使应用程序终止

我明白如何在后台检索位置。 而且我明白, 即使应用在iOS中终止,即使终止连续位置更新 ,也有机会获取位置信息

但。 我有应用程序移动和Foursquare。 如果这个应用程序甚至没有运行(我终止所有的应用程序,没有运行的应用程序),然后我去'隐私'和改变这个应用程序位置禁用(从不),我可以看到状态栏中的箭头消失。 但是,当我启用位置更新(总是),箭头再次出现在状态栏和应用程序不运行在这一刻。 所以这个应用程序开始采取地点的信息。 怎么样? 即使有些日子没有推出MOVE,这个应用程序然后显示我过去的日子正确的路线。 他们如何检索过去几天的位置信息,即使应用程序不启动?

我find了一个解决scheme。 这在IOS 9中工作。即使重新启动IOS设备,仍然运行。

http://mobileoop.com/getting-location-updates-for-ios-7-and-8-when-the-app-is-killedterminatedsuspended

GitHub示例: https : //github.com/voyage11/GettingLocationWhenSuspended

更新

您必须使用[myLocationManager startMonitoringSignificantLocationChanges] ,而不是[myLocationManager startUpdatingLocation]

下面,我的AppDelegate。

 @implementation LocationAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"didFinishLaunchingWithOptions"); self.shareModel = [LocationManager sharedManager]; self.shareModel.afterResume = NO; [self.shareModel addApplicationStatusToPList:@"didFinishLaunchingWithOptions"]; UIAlertView * alert; //We have to make sure that the Background App Refresh is enable for the Location updates to work in the background. if ([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusDenied) { alert = [[UIAlertView alloc]initWithTitle:@"" message:@"The app doesn't work without the Background App Refresh enabled. To turn it on, go to Settings > General > Background App Refresh" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil]; [alert show]; } else if ([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusRestricted) { alert = [[UIAlertView alloc]initWithTitle:@"" message:@"The functions of this app are limited because the Background App Refresh is disable." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil]; [alert show]; } else { // When there is a significant changes of the location, // The key UIApplicationLaunchOptionsLocationKey will be returned from didFinishLaunchingWithOptions // When the app is receiving the key, it must reinitiate the locationManager and get // the latest location updates // This UIApplicationLaunchOptionsLocationKey key enables the location update even when // the app has been killed/terminated (Not in th background) by iOS or the user. NSLog(@"UIApplicationLaunchOptionsLocationKey : %@" , [launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]); if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) { // This "afterResume" flag is just to show that he receiving location updates // are actually from the key "UIApplicationLaunchOptionsLocationKey" self.shareModel.afterResume = YES; [self.shareModel startMonitoringLocation]; [self.shareModel addResumeLocationToPList]; } } return YES; } - (void)applicationDidEnterBackground:(UIApplication *)application { NSLog(@"applicationDidEnterBackground"); [self.shareModel restartMonitoringLocation]; [self.shareModel addApplicationStatusToPList:@"applicationDidEnterBackground"]; } - (void)applicationDidBecomeActive:(UIApplication *)application { NSLog(@"applicationDidBecomeActive"); [self.shareModel addApplicationStatusToPList:@"applicationDidBecomeActive"]; //Remove the "afterResume" Flag after the app is active again. self.shareModel.afterResume = NO; [self.shareModel startMonitoringLocation]; } - (void)applicationWillTerminate:(UIApplication *)application { NSLog(@"applicationWillTerminate"); [self.shareModel addApplicationStatusToPList:@"applicationWillTerminate"]; } @end 

我的自定义LocationManager。

 @implementation LocationManager //Class method to make sure the share model is synch across the app + (id)sharedManager { static id sharedMyModel = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedMyModel = [[self alloc] init]; }); return sharedMyModel; } #pragma mark - CLLocationManager - (void)startMonitoringLocation { if (_anotherLocationManager) [_anotherLocationManager stopMonitoringSignificantLocationChanges]; self.anotherLocationManager = [[CLLocationManager alloc]init]; _anotherLocationManager.delegate = self; _anotherLocationManager.allowsBackgroundLocationUpdates = true; _anotherLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation; _anotherLocationManager.activityType = CLActivityTypeOtherNavigation; if(IS_OS_8_OR_LATER) { [_anotherLocationManager requestAlwaysAuthorization]; } [_anotherLocationManager startMonitoringSignificantLocationChanges]; } - (void)restartMonitoringLocation { [_anotherLocationManager stopMonitoringSignificantLocationChanges]; if (IS_OS_8_OR_LATER) { [_anotherLocationManager requestAlwaysAuthorization]; } [_anotherLocationManager startMonitoringSignificantLocationChanges]; } #pragma mark - CLLocationManager Delegate - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ NSLog(@"locationManager didUpdateLocations: %@",locations); for (int i = 0; i < locations.count; i++) { CLLocation * newLocation = [locations objectAtIndex:i]; CLLocationCoordinate2D theLocation = newLocation.coordinate; CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy; self.myLocation = theLocation; self.myLocationAccuracy = theAccuracy; } [self addLocationToPList:_afterResume]; } #pragma mark - Plist helper methods // Below are 3 functions that add location and Application status to PList // The purpose is to collect location information locally - (NSString *)appState { UIApplication* application = [UIApplication sharedApplication]; NSString * appState; if([application applicationState]==UIApplicationStateActive) appState = @"UIApplicationStateActive"; if([application applicationState]==UIApplicationStateBackground) appState = @"UIApplicationStateBackground"; if([application applicationState]==UIApplicationStateInactive) appState = @"UIApplicationStateInactive"; return appState; } - (void)addResumeLocationToPList { NSLog(@"addResumeLocationToPList"); NSString * appState = [self appState]; self.myLocationDictInPlist = [[NSMutableDictionary alloc]init]; [_myLocationDictInPlist setObject:@"UIApplicationLaunchOptionsLocationKey" forKey:@"Resume"]; [_myLocationDictInPlist setObject:appState forKey:@"AppState"]; [_myLocationDictInPlist setObject:[NSDate date] forKey:@"Time"]; [self saveLocationsToPlist]; } - (void)addLocationToPList:(BOOL)fromResume { NSLog(@"addLocationToPList"); NSString * appState = [self appState]; self.myLocationDictInPlist = [[NSMutableDictionary alloc]init]; [_myLocationDictInPlist setObject:[NSNumber numberWithDouble:self.myLocation.latitude] forKey:@"Latitude"]; [_myLocationDictInPlist setObject:[NSNumber numberWithDouble:self.myLocation.longitude] forKey:@"Longitude"]; [_myLocationDictInPlist setObject:[NSNumber numberWithDouble:self.myLocationAccuracy] forKey:@"Accuracy"]; [_myLocationDictInPlist setObject:appState forKey:@"AppState"]; if (fromResume) { [_myLocationDictInPlist setObject:@"YES" forKey:@"AddFromResume"]; } else { [_myLocationDictInPlist setObject:@"NO" forKey:@"AddFromResume"]; } [_myLocationDictInPlist setObject:[NSDate date] forKey:@"Time"]; [self saveLocationsToPlist]; } - (void)addApplicationStatusToPList:(NSString*)applicationStatus { NSLog(@"addApplicationStatusToPList"); NSString * appState = [self appState]; self.myLocationDictInPlist = [[NSMutableDictionary alloc]init]; [_myLocationDictInPlist setObject:applicationStatus forKey:@"applicationStatus"]; [_myLocationDictInPlist setObject:appState forKey:@"AppState"]; [_myLocationDictInPlist setObject:[NSDate date] forKey:@"Time"]; [self saveLocationsToPlist]; } - (void)saveLocationsToPlist { NSString *plistName = [NSString stringWithFormat:@"LocationArray.plist"]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docDir = [paths objectAtIndex:0]; NSString *fullPath = [NSString stringWithFormat:@"%@/%@", docDir, plistName]; NSMutableDictionary *savedProfile = [[NSMutableDictionary alloc] initWithContentsOfFile:fullPath]; if (!savedProfile) { savedProfile = [[NSMutableDictionary alloc] init]; self.myLocationArrayInPlist = [[NSMutableArray alloc]init]; } else { self.myLocationArrayInPlist = [savedProfile objectForKey:@"LocationArray"]; } if(_myLocationDictInPlist) { [_myLocationArrayInPlist addObject:_myLocationDictInPlist]; [savedProfile setObject:_myLocationArrayInPlist forKey:@"LocationArray"]; } if (![savedProfile writeToFile:fullPath atomically:FALSE]) { NSLog(@"Couldn't save LocationArray.plist" ); } } @end 

不要忘记在plist文件中启用背景位置。

在这里输入图像说明

并将消息设置为LocationAlwaysUsageDescription。

在这里输入图像说明