iOS:使 "Location" 出现在应用程序设置中而不请求位置授权(Tile 应用程序示例)
iOS: make "Location" appear in the app settings without requesting for location authorization (Tile app example)
长话短说:
我想让 "Location" 出现在应用程序设置中,而不像 Tile 应用程序那样请求位置授权。
重现步骤:
- 安装磁贴应用。
- 应用设置里没有"Location"
- 打开应用程序,接受蓝牙访问请求(有关系吗?)。
- 应用设置里还是没有"Location",但是出现了蓝牙
- 使用该应用约 20 秒(不能更短)。
- "Location" 出现在应用程序设置中 - 怎么办?
这是在下面的视频中展示的:
https://media.giphy.com/media/h5dPQPbBHzEhdLTrKz/giphy.gif
我怎样才能做到这一点?
背景 - 为什么
自 iOS 13 起,无法直接向用户请求 Always
位置授权。当开发者请求Always
授权时,用户只能select选择While in Use
选项,应用获得Provisional Always
授权。在再次提示用户之前(iOS 决定何时),用户将在应用程序设置中看到 While in Use
授权。
这意味着:
Always
--> CLAuthorizationStatus.authorizedAlways
和 Always
在应用程序设置中。
Provisional Always
--> 也 CLAuthorizationStatus.authorizedAlways
但 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
直接许可(无需两步),所以这不是必需的。
长话短说:
我想让 "Location" 出现在应用程序设置中,而不像 Tile 应用程序那样请求位置授权。
重现步骤:
- 安装磁贴应用。
- 应用设置里没有"Location"
- 打开应用程序,接受蓝牙访问请求(有关系吗?)。
- 应用设置里还是没有"Location",但是出现了蓝牙
- 使用该应用约 20 秒(不能更短)。
- "Location" 出现在应用程序设置中 - 怎么办?
这是在下面的视频中展示的:
https://media.giphy.com/media/h5dPQPbBHzEhdLTrKz/giphy.gif
我怎样才能做到这一点?
背景 - 为什么
自 iOS 13 起,无法直接向用户请求 Always
位置授权。当开发者请求Always
授权时,用户只能select选择While in Use
选项,应用获得Provisional Always
授权。在再次提示用户之前(iOS 决定何时),用户将在应用程序设置中看到 While in Use
授权。
这意味着:
Always
-->CLAuthorizationStatus.authorizedAlways
和Always
在应用程序设置中。Provisional Always
--> 也CLAuthorizationStatus.authorizedAlways
但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
直接许可(无需两步),所以这不是必需的。