如果已经为UIBackgroundModes的位置注册,iOS会唤醒已终止的应用吗?

asl*_*nci 23 location background ios

我知道,如果应用程序使用"重要更改位置服务",即使应用程序已终止,iOS也会在有位置更新时将其唤醒.

如果应用程序使用标准位置服务并指定位置作为UIBackgroundModes的密钥,我无法找到关于此案例的明确答案:iOS是否也会将其唤醒以提供更新,即使它已终止?或者应用程序是否需要在后台运行以获取位置更新回调?

更新:当我问这个时,我没有时间去测试它.但是在我得到答案后,我在我的应用程序的委托中编写了这段代码,看看我的终止应用程序是否会在获得位置更新时重新启动.当我收到更新通知时,我正在显示UILocalNotification.但是,当我终止我的应用程序,然后更改我在城市的位置,该应用程序没有重新启动,我没有得到任何更新.你能告诉我我做错了什么吗?

更新#2:根据此问答中的最终结果,此代码没有任何问题,这是使用标准位置服务的应用程序的预期行为,而不是在终止后重新启动.

我已将位置添加为Info.plist文件中的UIBackgroundModes之一.

这是我的应用代表的位置相关部分:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    [UIApplication sharedApplication].applicationIconBadgeNumber = 0;

    m_locManager = [[CLLocationManager alloc] init];
    m_locManager.delegate = self;
    [m_locManager startUpdatingLocation];
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [m_locManager startUpdatingLocation];
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog("%@", [NSString stringWithFormat:@"Background Fail %@", [error localizedDescription]]);
}

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation
{
    UILocalNotification * theNotification = [[UILocalNotification alloc] init];
    theNotification.alertBody = [NSString stringWithFormat:@"Background location %.06f %.06f %@" , newLocation.coordinate.latitude, newLocation.coordinate.longitude, newLocation.timestamp];
    theNotification.alertAction = @"Ok";

    theNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:1];

    [[UIApplication sharedApplication] scheduleLocalNotification:theNotification];
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*l J 5

看起来您找到了一个可行的解决方案,而且使用重大更改框架似乎可以为您节省一些电池寿命,只要它对您的目的来说足够准确。您的解决方案也是有益的,因为它允许您通过仅监控您最接近的区域来处理可能超过每个应用程序允许同时监控 20 个区域的限制。

我需要类似的功能,但认为重大变化对我的应用程序来说不够准确,所以我又挖掘了一些并找到了以下内容。

根据位置感知编程指南,在“监控基于形状的区域”下:

在 iOS 中,与您的应用程序相关联的区域始终被跟踪,包括您的应用程序未运行时。如果在应用程序未运行时跨越区域边界,则该应用程序将重新启动到后台以处理该事件。类似地,如果应用在事件发生时被挂起,它会被唤醒并有很短的时间来处理事件。

还有在“处理一个区域的边界交叉事件”中:

每次用户当前位置跨越边界区域时,系统都会为您的应用生成一个适当的区域事件。如果您的应用程序已经在运行,这些事件将直接发送到任何当前位置管理器对象的委托。如果您的应用程序未运行,系统会在后台启动它以便它可以响应。应用程序可以实现以下方法来处理越界:

locationManager:didEnterRegion:

locationManager:didExitRegion:

就我而言,我只需要在越过边界时触发通知,因此我将 AppDelegate 设置为符合 CLLocationManagerDelegate,创建了一个 locationManager 属性,并将其放入我的实现文件中:

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.locationManager.delegate = self;
    return YES;
}

- (CLLocationManager *)locationManager
{
    if (!_locationManager) {
        _locationManager = [[CLLocationManager alloc] init];
        _locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
    }
    return _locationManager;
}

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    notification.alertBody = NSLocalizedString(@"You crossed a boundary!", @"user crossed a boundary");
    [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
Run Code Online (Sandbox Code Playgroud)

测试表明无需设置 UIBackgroundModes 位置键即可工作。在这个用例中,操作系统为您处理边界监控,然后将事件发送到您的应用程序,时间刚好足以处理该事件。这不会启动应用程序,它只是在后台运行几秒钟来处理边界事件,在此期间您只能进行相关活动。希望这对其他人也有帮助!


bor*_*den 4

是的,它的行为方式相同,只是它会更频繁地接收更新(从而消耗更多电池)。

来源:跟踪用户位置部分下的应用程序状态和多任务处理

编辑重新阅读后,似乎程序将从挂起状态中唤醒,但不会从终止状态中唤醒。不过,我认为您并不真正需要这种后台模式。它专为需要精细位置信息(例如路线导航)的应用程序而设计。查看位置编程指南中有关“基于区域”编程的部分。您评论中的示例被列为该应用程序的用途之一。

再次编辑根据评论中的讨论,最终的解决方案似乎是设置显着的位置更改,直到用户足够接近,然后切换到精细位置更改(并希望应用程序在此期间不会被终止^^ )