定位權限請求時易犯的錯誤小結


起因

用戶群反饋app可能請求了不合適的定位權限:始終定位。

看到這個截圖,根據經驗判斷可能是后台定位功能導致可能不得不請求始終定位權限。再加上之前提交審核時,蘋果要求在plist文件中新增NSLocationAlwaysAndWhenInUseUsageDescription和NSLocationAlwaysUsageDescription鍵值對。猜測可能是對某些點的理解混淆了,因為這種用戶體驗的確不好。

解決思路

因為此項目是前同事遺留代碼,自從接手后迭代次數比較有限。於是計划根據以下步驟進行排查和驗證:

  • 查現有代碼和plist文件
  • 查官方文檔
  • 改工程代碼
  • 提交審核,查看郵件提醒
  • app退入后台,查看定位信息是否輸出

查plist文件和權限請求代碼

plist文件

以下鍵都已加入:

NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
NSLocationAlwaysAndWhenInUseUsageDescription

權限請求代碼

全局搜索request,找到定位權限請求代碼,發現

  if ([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
            [_locationManager requestAlwaysAuthorization];
   }

查官方文檔

plist文件配置

  • NSLocationAlwaysUsageDescription

Discussion
Use this key if your iOS app accesses location information in the background, and you deploy to a target earlier than iOS 11. In that case, add both this key and NSLocationAlwaysAndWhenInUseUsageDescription to your app’s Info.plist file with the same message. Apps running on older versions of the OS use the message associated with NSLocationAlwaysUsageDescription, while apps running on later versions use the one assocated with NSLocationAlwaysAndWhenInUseUsageDescription.
If your app only needs location information when in the foreground, use NSLocationWhenInUseUsageDescription instead. For more information, see Choosing the Authorization Level for Location Services.
If you need location information in a macOS app, use NSLocationUsageDescription instead.
Important
This key is required if your iOS app uses APIs that access the user’s location at all times and deploys to targets earlier than iOS 11.

  • NSLocationWhenInUseUsageDescription

Discussion
Use this key if your iOS app accesses location information only when running in the foreground. If your app needs location information when in the background, use NSLocationAlwaysAndWhenInUseUsageDescription instead. For more information, see Choosing the Authorization Level for Location Services.
If you need location information in a macOS app, use NSLocationUsageDescription instead.
Important
This key is required if your iOS app uses APIs that access the user’s location information while the app is running in the foreground.

  • NSLocationAlwaysAndWhenInUseUsageDescription

Discussion
Use this key if your iOS app accesses location information while running in the background. If your app only needs location information when in the foreground, use NSLocationWhenInUseUsageDescription instead. For more information, see Choosing the Authorization Level for Location Services.
If you need location information in a macOS app, use NSLocationUsageDescription instead. If your iOS app deploys to versions earlier than iOS 11, see NSLocationAlwaysUsageDescription.
Important
This key is required if your iOS app uses APIs that access the user’s location information at all times.

對比可知:

  • 如果app需要前台運行定位權限,需要配置NSLocationWhenInUseUsageDescription;
  • 如果app需要后台運行定位權限,需要配置NSLocationAlwaysAndWhenInUseUsageDescription;如果適配iOS11之前版本,還需要配置NSLocationAlwaysUsageDescription

這幾種鍵的區別主要在於區分app 前后台運行 時的權限配置。

權限請求代碼

requestAlwaysAuthorization

When the user grants “Always” authorization to your app, your app can start any of the available location services while your app is running in the foreground or background. In addition, services that allow your app to be launched in the background continue to do so.
Important
Requesting “Always” authorization is discouraged because of the potential negative impacts to user privacy. You should request this level of authorization only when doing so offers a genuine benefit to the user.

requestWhenInUseAuthorization

You must call this method or the requestAlwaysAuthorization()method prior to using location services. If the user grants “when-in-use” authorization to your app, your app can start most (but not all) location services while it is in the foreground. (Apps cannot use any services that automatically relaunch the app, such as region monitoring or the significant location change service.) When started in the foreground, services continue to run in the background if your app has enabled background location updates in the Capabilities tab of your Xcode project. Attempts to start location services while your app is running in the background will fail. The system displays a location-services indicator in the status bar when your app moves to the background with active location services.

官方建議:

The type of authorization (“when-in-use” or “always”) that you request determines which location services your app can access and when it can use them:

When-in-use authorization. Your app can use most services but cannot use services that automatically relaunch the app. Your app must always start services while running in the foreground. If you enable the background location capability for your app, a suspended app will wake in the background to handle location events. However, if your app is not running, it will not be launched.

Always authorization. Your app can use all location services, and it can start those services from either the foreground or the background. If a location-related event occurs when your app is not running, the system launches your app and delivers the event.

官方更詳細說明:

https://developer.apple.com/documentation/corelocation/choosing_the_location_services_authorization_to_request

改工程代碼

  • 保持plist配置不變
  • 修復請求方法:
  if ([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
            [_locationManager requestWhenInUseAuthorization];
  }

提交審核,查看郵件提醒

新增version,打包上傳,查看郵件提醒:並未提及定位權限有何問題。

app退入后台,查看定位信息是否輸出

為驗證app退到后台依舊可以定位,故實測退到后台后,gps回調方法中log是否持續輸出,結果:會!

結論

plist權限配置的定義和通過代碼請求權限不是絕對的一一對應關系,容易被誤解,前同事也是在這個地方混淆了。這也是本bug出現的根本原因。
以后遇到類似易混淆概念,還是查好多篇相關官方文檔,並充分理解后再寫代碼比較好。關於本知識點,網上有的教程可能會混淆,請注意鑒別。

  • 讓我們杜絕淺嘗輒止,追求精益求精!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM