首页 文章

位置服务不在WatchKit调用的后台工作

提问于
浏览
1

我的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委托 .

-(void)runLocationUpdate
{
    [self.locationManager startUpdatingLocation];
}

1 回答

  • 3

    要检查和注意的三件事:

    • 位置权限如 [self.locationManager requestAlwaysAuthorization]; 仅由OS确认一次 . 如果您已经请求了权限,则无论级别如何,操作系统都不会向用户显示请求 . 操作系统将仅传递请求并保留权限级别 . 只有当 [CLLocationManager authorizationStatus] 返回 kCLAuthorizationStatusNotDetermined 时,才能确保操作系统向用户显示请求的唯一时间 . 在所有其他情况下,您必须通过显示警报或其他形式的UI显示来手动请求权限 . 另请注意,即使您删除了应用并重新安装,操作系统仍会保留其是否已显示请求 . 所以要测试,你需要重置你的模拟器's Content or your iPhone'位置隐私 .

    • 确保已为 NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription 添加了plist键如果不将其添加到plist,操作系统将忽略任何位置权限请求 .

    • 如果您想在手机应用程序处于后台时使用 requestAlwaysAuthorization 从手机(而不是 Watch 应用程序扩展程序)获取位置数据,还需要在项目>目标>功能下注册后台模式位置更新 .

    UPDATE 使用后台任务可以让您的应用有时间在后台进行响应 . 像这样的东西:

    -(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;
        });
    }
    

相关问题