对iOS定位授权弹窗机制的理解

一、概述

由于最近在开发跑步相关的功能,涉及到地图定位功能,因此需要申请定位权限,之前APP中有定位需要,但因之前未细致的研究授权模式的配置,导致在开发跑步功能时产生了从未遇到的异常问题。

二、遇到的问题

  • 问题描述:

问题描述:首次安装APP,授权定位权限为WhenInUse使用期间定位定位,然后开启跑步,此时接收定位回调,将APP切入后台等待3-5秒钟后,发现定位回调不再继续回调给APP,此时将APP返回前台,将恢复定位回调,可接收到定位结果数据。然后再将APP切回后台,这时会再次弹出定位模式选择弹窗,内容为”保持仅使用期间“和”更改为始终允许“。

  1. 选择”保持仅使用期间“:
    会报错误
定位发生错误Error Domain=com.baidu.location.locationerrordomain Code=2 
"手机不允许定位,请确认用户授予定位权限或者手机是否打开定位开关" 
UserInfo={NSLocalizedDescription=手机不允许定位,
请确认用户授予定位权限或者手机是否打开定位开关}

注:此时定位模式被切换到whenInUse使用期间定位模式,前后台定位功能可正常使用

  1. 选择”更改为始终允许“:
    此时定位模式被切换到Always始终定位模式,前后台定位功能可正常使用
  • 问题的思考:
    经过对代码实现的调查发现,启动时申请定位权限时使用的requestAlwaysAuthorization,而不是requestWhenInUseAuthorization,虽然两者弹出的系统弹窗相同,但是使用流程上是有区别的。因为我们的APP之前使用了Always申请始终定位权限,虽然在首次弹窗是选择了”使用APP时允许“但是我们在打印授权状态时是kCLAuthorizationStatusAuthorizedAlways始终定位状态,这和我们选择的”使用APP时允许“初衷有所不同。那如何正确申请定位模式呢?

三、定位基础

  • locationServicesEnabled

系统全局定位开关,确定用户是否启用了位置服务,如果返回NO,需要提示用户到设置隐私中开启定位服务。

  • @property (nonatomic, readonly) CLAuthorizationStatus authorizationStatus

返回应用程序当前定位授权状态

typedef NS_ENUM(int, CLAuthorizationStatus) {
      kCLAuthorizationStatusNotDetermined = 0,  // 用户未授权,即还未弹出OS的授权弹窗
      kCLAuthorizationStatusDenied, // 用户拒绝定位权限,包括拒绝App或者全局开关关闭
      kCLAuthorizationStatusRestricted, // 定位服务受限,该状态位用户无法通过设置页面进行改变
      kCLAuthorizationStatusAuthorizedAlways, // 始终定位,即后台定位
      kCLAuthorizationStatusAuthorizedWhenInUse, // App使用的时候,允许定位
      kCLAuthorizationStatusAuthorized, // iOS8.0之后已经被废弃
};
  • @property (nonatomic, readonly) CLAccuracyAuthorization accuracyAuthorization

返回应用程序当前定位的精确度

typedef NS_ENUM(NSInteger, CLAccuracyAuthorization) {
    CLAccuracyAuthorizationFullAccuracy, //精准定位
    CLAccuracyAuthorizationReducedAccuracy, // 模糊定位
};
  • @property(weak, nonatomic, nullable) id<CLLocationManagerDelegate> delegate;

定位的代理实例,定位状态的变化会在CLLocationManagerDelegate的方法中回调

  • @property(assign, nonatomic) BOOL pausesLocationUpdatesAutomatically

指定定位是否会被系统自动暂停,默认是YES

  • @property(assign, nonatomic) BOOL allowsBackgroundLocationUpdates

是否允许后台定位,默认是NO

  • requestWhenInUseAuthorization

申请使用期间定位模式,下面会详细解释

  • (void)requestAlwaysAuthorization

申请始终定位模式,下面会详细解释

四、使用期间定位模式

  • 需要在Info.plist中配置NSLocationWhenInUseUsageDescription;
  • 调用方法requestWhenInUseAuthorization申请使用期间定位模式,必须在status = kCLAuthorizationStatusNotDetermined的时候,调用才会出现系统弹窗,否则无响应;
  • APP必须在前台运行时才会显示系统弹窗
  • 系统弹窗选项:
选项 授权
使用App时允许 APP使用时授权,不会失效status = WhenInUse
允许一次 临时授权,授权后status = WhenInUse ,下次再次启动App时授权会失效 status = notDetermined
不允许 拒绝授权,不允许授权请求status = Denied
  • 当应用程序在前台开启正常使用时定位权限后,如果在Xcode中开启后台定位刷新的能力,定位服务仍然可以在后台继续运行;
  • 当应用程序切换到具有后台位置更新服务的后台时,系统会在状态栏中显示蓝色位置服务指示器,表示定位仍在进行中;

在iOS 16及更高版本中,主动跟踪用户位置或最近启用核心位置的应用程序会在Control Center中显示一个指示器。

  • 之后如果还需要定位,则需要自己弹窗提醒用户。

五、始终定位模式

  • 需要在Info.plist中配置NSLocationAlwaysAndWhenInUseUsageDescriptionNSLocationWhenInUseUsageDescription如果需要支持 iOS10 的话需要配置 NSLocationAlawaysUsageDescription
  • 可以在授权状态为notDeterminedwhenInUse时可调用requestAlwaysAuthorization
  • 系统对requestAlwaysAuthorization 方法的调用是有一定的限制的,当APP调用此方法后,在继续进一步调用是无响应的,也就是说不可以连续调用;
  • 授权方式
    A、 先获取"使用期间定位"模式后,再申请"始终定位"权限
        获取Always权限前应用程序需要先获取到whenInUse权限,然后再请求Always授权。
        1、如果APP在获取whenInUse权限后,立即调用requestAlwaysAuthorization方法,系统会立即提示用户是否授权Always权限或保持whenInUse权限。
        2、如果用户选择”仅允许一次“授权后,则系统会忽略requestAlwaysAuthorization方法的任何调用,此时属于临时授权状态。
选项 授权
保持仅使用期间 定位权限将继续保持为使用期间定位,代理未收到任何回调status = WhenInUse
更改为始终允许 定位权限将修改为始终定位,代理会收到状态变化回调status = authorizedAlways

当 status = notdetermined时,调用requestWhenInUseAuthorization,只有用户同意“使用App时允许”的情况下才有用,然后当 status = WhenInUse时,调用requestAlwaysAuthorization或系统查觉到APP需要”始终“定位时,会再次出现始终授权模式弹窗。

B、直接申请获取"始终定位"权限
如果APP在定位授权状态为notDetermined时,此时调用requestAlwaysAuthorization方法后,系统会出现两次弹窗。
1、第一次弹窗与申请”使用期间定位“权限时相同;但是选择”使用App时允许“意义有所不同

选项 授权
使用App时允许 APP获得临时的”始终“定位权限,status = authorizedAlways
允许一次 临时授权,授权后status = WhenInUse ,下次再次启动App时授权会失效 status = notDetermined
不允许 拒绝授权,不允许授权请求status = Denied

2、第二次弹窗的时机:

  • 当系统准备向APP传递的事件需要authorizedAlways权限时;
  • 如果APP处于临时”始终“定位状态时;
  • 当APP进入后台进入非活跃状态挂起时;
选项 授权
保持仅使用期间 系统将授权由临时”始终“更改为”使用期间“,代理会收到状态变化事件,status = WhenInUse
更改为始终允许 移除临时”始终”定位权限,变为“始终”授权状态,代理不会会收到状态变化回调,status = authorizedAlways

注:如果用户在提示出现后做出选择,并选择允许“始终”权限,则位置事件将发送到您的应用程序。

六、确定应用需要的授权限

A、应用程序的定位授权状态决定了其是否需要及何时接收定位事件:

  • When In Use(APP使用期间定位)
    您的应用程序可以在使用中使用所有位置服务并接收事件。一般来说,如果iOS应用程序位于前台或在后台运行,并且后台位置使用指示器已启用,则视为正在使用。
  • Always(APP总是定位)
    您的应用程序可以使用所有位置服务并接收事件,即使用户不知道您的应用程序正在运行。如果你的应用程序未运行,系统将启动你的应用程序并传递事件。
  • “使用期间定位”是首选模式
    B、尽可能的请求授权使用“使用期间定位”模式,此模式具有强大的功能,允许您的应用程序:
    1、在用户使用应用程序时访问所有可用的位置服务。如果用户停止使用你的应用程序,任何未完成的请求都将挂起,直到用户恢复使用你的应用程序为止,才会恢复定位服务
    2、如果您在Xcode项目中启用了后台位置更新,即使在应用程序进入后台后,也可以继续获取位置更新。
    3、使用位置通知触发器启动。如果您的应用程序可以依赖用户的交互,请设置UNLocationNotificationTrigger,以在用户进入相关区域时通知用户。当用户点击通知时,系统启动应用程序,使其有资格接收位置事件。此方法允许用户在相关时刻决定是否与您的应用程序共享其位置。
    C、当应用程序授权“使用期间定位”时,如何确定应用程序正在使用后定位?
    1、当应用程序在前台运行时;
    2、在应用程序离开前台后进入后的几秒钟内,您的应用程序将有一个短的宽时间限期来完成用户启动的任何当前位置任务;
    3、当应用程序显示后台位置使用指示器(showsBackgroundLocationIndicator)时。在iOS上,指示灯是屏幕顶部的蓝色条或小球;
    D、请求"始终"授权:
    在以下情况下,您可能需要请求始终授权:
    1、您的应用程序执行自动任务,在此期间可能会不方便或不需要的显示提示;
    2、你的应用程序记录了一天中的许多位置,例如日记应用程序。用户可能更倾向于允许始终授权,以便您的应用程序即使在未使用时也可以记录位置,而无需提示用户;

请记住,请求授权并不能保证你的应用程序会收到授权。如果您请求“始终定位”授权,则用户可以选择在使用时授予您的应用程序授权。您必须始终准备好在使用授权时运行。

注:如果您的应用程序已经授权“使用时定位”授权,您可以稍后单独请求Always authorization。然而,应用程序可能只发出一个始终授权请求。

七、结束语

经过分析和验证试验,确定在我的APP中定位回调异常问题是因为请求授权方式使用错误,优先使用When In Use定位模式,然后在需要使用Always”定位权限的位置再申请权限。当APP得到定位模式被用户选择为“When In Use”时,进入后台观察左上角是否有定位指示器(蓝色图标),存在的话可以确定当前定位服务正常。如果选择Always模糊,那么屏幕左上角会显示定位图标。

官方文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容