ios - WatchKit 调用的定位服务在后台不工作

标签 ios background watchkit location-services

我的 Apple Watch 应用程序需要一些数据,并从相应的 iPhone 应用程序请求这些数据。为了满足请求,iPhone 应用程序需要用户位置。
在使用真正的 Apple Watch 进行接收和测试后,我发现我的 iPhone 应用在后台运行时没有接收到位置更新。如果 iPhone 应用程序在前台处于事件状态,则它可以正常工作。使用模拟器,它在这两种情况下都有效。

在这两种情况下(事件和后台),WatchKit 扩展程序调用并成功启动 iPhone 应用程序并一直运行,直到在 iPhone 应用程序中调用 startUpdatingLocation。但是如果应用程序在后台运行,didUpdateLocations 永远不会被调用。

我尝试了 requestAlwaysAuthorization 和 requestWhenInUseAuthorization。没有不同。
然后我还激活了功能内的“位置更新”后台模式。但又没有区别。

是否有其他人面临同样的问题并找到了一种在后台也接收位置的方法?

这里有一些代码。首先检查是否需要授权。

// iOS 8 check to avoid crash on older iOS
    if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
    {
        [self requestLocationAlwaysAuthorization];
    }
    else
    {
        [self runLocationUpdate];
    }

在这里检查正确的位置管理员权限。
- (void)requestLocationAlwaysAuthorization
{
CLAuthorizationStatus currentAuthStatus = [CLLocationManager authorizationStatus];

if (currentAuthStatus == kCLAuthorizationStatusDenied)
{
    //request user to change setting
}
else if (currentAuthStatus == kCLAuthorizationStatusRestricted)
{
    //request user to change setting
}
else if (currentAuthStatus == kCLAuthorizationStatusNotDetermined)
{
    [self.locationManager requestAlwaysAuthorization];

    [self runLocationUpdate];
}
else if (currentAuthStatus == kCLAuthorizationStatusAuthorizedWhenInUse)
{
    //maybe when in use is also enough?
    [self runLocationUpdate];
}
else if (currentAuthStatus == kCLAuthorizationStatusAuthorizedAlways)
{
    //all ok
    [self runLocationUpdate];
}

}

这里调用 startUpdatingLocation。只有在 iPhone 应用程序处于事件状态时才会调用 didUpdateLocations 委托(delegate)。
-(void)runLocationUpdate
{
    [self.locationManager startUpdatingLocation];
}

最佳答案

需要检查和注意的三件事:

  • 位置权限,如 [self.locationManager requestAlwaysAuthorization];操作系统只确认一次。如果您已经请求权限,无论级别如何,操作系统都不会向用户显示请求。操作系统只会传递请求并保持权限级别不变。只有在 [CLLocationManager authorizationStatus] 的情况下,操作系统才会向用户显示请求。返回 kCLAuthorizationStatusNotDetermined .在所有其他情况下,您必须通过显示警报或其他形式的 UI 显示来手动请求权限。另请注意,操作系统会保留它是否已显示请求,即使您删除应用程序并重新安装它也是如此。因此,要进行测试,您需要重置模拟器的内容或 iPhone 的位置隐私。
  • 确保您已为 NSLocationAlwaysUsageDescription 添加了 plist 键。和 NSLocationWhenInUseUsageDescription如果您不将此添加到您的 plist,操作系统将忽略任何位置权限请求。
  • 如果你想使用 requestAlwaysAuthorization要在手机应用程序处于后台时从手机(不是 watch 应用程序扩展程序)获取位置数据,还需要您在项目>目标>功能下注册后台模式位置更新。

  • 更新
    使用后台任务让您的应用程序有时间在后台响应。像这样的东西:
    -(void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *replyInfo))reply{
    
        UIApplication *app = [UIApplication sharedApplication];
    
        UIBackgroundTaskIdentifier bgTask __block = [app beginBackgroundTaskWithName:@"watchAppRequest" expirationHandler:^{
    
            [[UIApplication sharedApplication] endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;
    
        }];
    
    //make your calls here to your tasks, when finished, send the reply then terminate the background task
    
    //send reply back to watch
    reply(replyInfo);
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
            [app endBackgroundTask:bgTask];
            bgTask=UIBackgroundTaskInvalid;
        });
    }
    

    关于ios - WatchKit 调用的定位服务在后台不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30240852/

    相关文章:

    ios - WatchKit WKInterfaceMovie fatal error : unexpectedly found nil while unwrapping an Optional value

    ios - WatchOS 和位置权利

    ios - 像 UITabBarItem 一样在 UIBarButtonItem 下添加标签

    ios - 如何检查应用程序是否在 iOS 设备或模拟器上运行

    iphone - 开始和停止按钮,需要禁用和隐藏然后重新启用和可见

    html - CSS 后台语法问题

    google-chrome - chrome 扩展 OnMessage

    ios - 使用缓冲从 objective-c 中的 url 播放视频

    javascript - objective-c SS : Background image Javascript

    ios - UIView --> 不可见 View 的 UIImage?