iOS 9即使应用终止也如何获取位置 [英] iOS 9 how get locations even if app terminated

查看:220
本文介绍了iOS 9即使应用终止也如何获取位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解如何在后台检索位置.而且我知道即使终止

I understand how retrieve locations in background. And I understand that there is a chance to get locations even if terminated Continious location updates even if app is terminated in iOS

但是.我有应用Moves和Foursquare.如果该应用程序甚至没有运行(我终止了所有应用程序,并且没有应用程序在运行),然后转到隐私"并更改了此应用程序的位置以将其禁用(从不),则可以看到状态栏中的箭头消失了.但是,当我启用位置更新(始终)时,状态栏中再次出现箭头,并且此刻应用程序未运行.因此,此应用开始获取有关位置的信息.如何?即使有几天没有启动MOves,此应用也会向我显示过去几天的正确路线.他们如何检索过去几天的位置信息,甚至没有启动应用程序?

But. I have app Moves and Foursquare. If this app even not running (I terminate all apps and no apps running) and then I go to 'Privacy' and change for this apps locations to disable (Never), I can see that arrow in status bar disappeared. But when I enable location updates (Always), arrow again appeared in status bar and apps not running in this moment. So this apps begin take info about locations. How? Even If not launch MOves for some days, this app then show me right route for past days. How they retrieve location info about past days, even app not launching?

推荐答案

我找到了解决方案. 这在IOS 9中对我有用.即使重新启动IOS设备,它仍然可以运行.

I found a solutions for this. This worked for me in IOS 9. Even restarting the IOS device, keeps running.

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

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

The GitHub sample: https://github.com/voyage11/GettingLocationWhenSuspended

更新

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

下面是我的AppDelegate.

Below, the my 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.

My custom 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文件中启用背景位置.

Do not forget of enable backgound location in plist file.

并将消息设置为LocationAlwaysUsageDescription.

And set message to LocationAlwaysUsageDescription.

这篇关于iOS 9即使应用终止也如何获取位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆