iOS:使 "Location" 出现在应用程序设置中而不请求位置授权(Tile 应用程序示例)

iOS: make "Location" appear in the app settings without requesting for location authorization (Tile app example)

长话短说:

我想让 "Location" 出现在应用程序设置中,而不像 Tile 应用程序那样请求位置授权。

重现步骤:

  1. 安装磁贴应用。
    • 应用设置里没有"Location"
  2. 打开应用程序,接受蓝牙访问请求(有关系吗?)。
    • 应用设置里还是没有"Location",但是出现了蓝牙
  3. 使用该应用约 20 秒(不能更短)。
    • "Location" 出现在应用程序设置中 - 怎么办?

这是在下面的视频中展示的:

https://media.giphy.com/media/h5dPQPbBHzEhdLTrKz/giphy.gif

我怎样才能做到这一点?


背景 - 为什么

自 iOS 13 起,无法直接向用户请求 Always 位置授权。当开发者请求Always授权时,用户只能select选择While in Use选项,应用获得Provisional Always授权。在再次提示用户之前(iOS 决定何时),用户将在应用程序设置中看到 While in Use 授权。

这意味着:

这在 中有详细描述。

The problem is that the application cannot read the location in the background without Always authorization(可以,但只能持续5-10秒),这极大地限制了某些应用程序(例如iBeacon trackers)的主要功能。

一个众所周知的做法是检查应用程序是否具有 Always 授权,如果没有,则提供说明为什么这很重要以及用户如何更改它的信息(在设置中手动)。

但是我们无法区分是Always还是Provisional Always授权状态(at least directly),所以逻辑:

if (CLLocationManager.authorizationStatus() != .authorizedAlways) {
    // Prompt the user to change Location access to Always manually in settings
}

不适用于 Provisional Always 授权状态。

解决方法可以是要求用户在请求位置授权之前在设置中手动选择Always,以防止出现Provisional Always状态。我认为不先调用 requestAlwaysAuthorization() 是不可能的,但是 Tile 以某种方式做到了,如上一个视频所示。

更新:

我已经有:

  • NSLocationAlwaysAndWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription
  • NSLocationWhenInUseUsageDescription

在 Info.plist 文件中设置了私钥。

您是否尝试过简单地将 NSLocationAlwaysAndWhenInUseUsageDescription 键放入您的 plist,然后实例化一个 CLLocationServices 实例并使用它来尝试启动位置更新?我怀疑这会导致该条目出现在设置中,即使位置更新在获得许可之前不会起作用。

要在应用程序设置中显示 "Location" 而不先征求许可(Always 需要两步选择加入),您需要调用 locationManager.requestLocation().

func scheduleLocationUpdates() {
    if CLLocationManager.locationServicesEnabled() && CLLocationManager.authorizationStatus() == .authorizedAlways {
        locationManager.startUpdatingLocation()
        // hide full screen instruction (if shown)
    } else {
        if (UIDevice.current.systemVersion as NSString).floatValue >= 13.0 {
            locationManager.requestLocation() // reveal "Location" in app settings (works on iOS 13 only)
            // show full screen instruction how to provide "Always authorization"
        } else {
            if CLLocationManager.authorizationStatus() == .notDetermined {
                locationManager.requestAlwaysAuthorization()
            } else {
                // show full screen instruction how to provide "Always authorization"
            }
        }
    }
}

函数 scheduleLocationUpdates() 应在 viewWillAppear 中和 UIApplication.willEnterForegroundNotification 事件之后调用(例如,当用户从“设置”返回时)。

On iOS 12 "Location" 将不会出现在应用程序设置中,除非先征求许可。 但您可以征求 Always 直接许可(无需两步),所以这不是必需的。