一、概述
由于最近在開(kāi)發(fā)跑步相關(guān)的功能,涉及到地圖定位功能蒙具,因此需要申請(qǐng)定位權(quán)限,之前APP中有定位需要峰弹,但因之前未細(xì)致的研究授權(quán)模式的配置店量,導(dǎo)致在開(kāi)發(fā)跑步功能時(shí)產(chǎn)生了從未遇到的異常問(wèn)題。
二鞠呈、遇到的問(wèn)題
- 問(wèn)題描述:
問(wèn)題描述:首次安裝APP融师,授權(quán)定位權(quán)限為
WhenInUse
使用期間定位定位,然后開(kāi)啟跑步蚁吝,此時(shí)接收定位回調(diào)旱爆,將APP切入后臺(tái)等待3-5秒鐘后,發(fā)現(xiàn)定位回調(diào)不再繼續(xù)回調(diào)給APP窘茁,此時(shí)將APP返回前臺(tái)怀伦,將恢復(fù)定位回調(diào),可接收到定位結(jié)果數(shù)據(jù)山林。然后再將APP切回后臺(tái)房待,這時(shí)會(huì)再次彈出定位模式選擇彈窗,內(nèi)容為”保持僅使用期間“和”更改為始終允許“驼抹。
-
選擇”保持僅使用期間“:
會(huì)報(bào)錯(cuò)誤
定位發(fā)生錯(cuò)誤Error Domain=com.baidu.location.locationerrordomain Code=2
"手機(jī)不允許定位桑孩,請(qǐng)確認(rèn)用戶授予定位權(quán)限或者手機(jī)是否打開(kāi)定位開(kāi)關(guān)"
UserInfo={NSLocalizedDescription=手機(jī)不允許定位,
請(qǐng)確認(rèn)用戶授予定位權(quán)限或者手機(jī)是否打開(kāi)定位開(kāi)關(guān)}
注:此時(shí)定位模式被切換到
whenInUse使用期間定位模式框冀,前后臺(tái)定位功能可正常使用
-
選擇”更改為始終允許“:
此時(shí)定位模式被切換到Always
始終定位模式流椒,前后臺(tái)定位功能可正常使用
- 問(wèn)題的思考:
經(jīng)過(guò)對(duì)代碼實(shí)現(xiàn)的調(diào)查發(fā)現(xiàn),啟動(dòng)時(shí)申請(qǐng)定位權(quán)限時(shí)使用的requestAlwaysAuthorization
明也,而不是requestWhenInUseAuthorization
宣虾,雖然兩者彈出的系統(tǒng)彈窗相同惯裕,但是使用流程上是有區(qū)別的。因?yàn)槲覀兊腁PP之前使用了Always
申請(qǐng)始終定位權(quán)限绣硝,雖然在首次彈窗是選擇了”使用APP時(shí)允許“但是我們?cè)诖蛴∈跈?quán)狀態(tài)時(shí)是kCLAuthorizationStatusAuthorizedAlways
始終定位狀態(tài)蜻势,這和我們選擇的”使用APP時(shí)允許“初衷有所不同。那如何正確申請(qǐng)定位模式呢鹉胖?
三咙边、定位基礎(chǔ)
- locationServicesEnabled
系統(tǒng)全局定位開(kāi)關(guān),確定用戶是否啟用了位置服務(wù)次员,如果返回NO败许,需要提示用戶到設(shè)置隱私中開(kāi)啟定位服務(wù)。
- @property (nonatomic, readonly) CLAuthorizationStatus authorizationStatus
返回應(yīng)用程序當(dāng)前定位授權(quán)狀態(tài)
typedef NS_ENUM(int, CLAuthorizationStatus) {
kCLAuthorizationStatusNotDetermined = 0, // 用戶未授權(quán)淑蔚,即還未彈出OS的授權(quán)彈窗
kCLAuthorizationStatusDenied, // 用戶拒絕定位權(quán)限市殷,包括拒絕App或者全局開(kāi)關(guān)關(guān)閉
kCLAuthorizationStatusRestricted, // 定位服務(wù)受限,該狀態(tài)位用戶無(wú)法通過(guò)設(shè)置頁(yè)面進(jìn)行改變
kCLAuthorizationStatusAuthorizedAlways, // 始終定位刹衫,即后臺(tái)定位
kCLAuthorizationStatusAuthorizedWhenInUse, // App使用的時(shí)候醋寝,允許定位
kCLAuthorizationStatusAuthorized, // iOS8.0之后已經(jīng)被廢棄
};
- @property (nonatomic, readonly) CLAccuracyAuthorization accuracyAuthorization
返回應(yīng)用程序當(dāng)前定位的精確度
typedef NS_ENUM(NSInteger, CLAccuracyAuthorization) {
CLAccuracyAuthorizationFullAccuracy, //精準(zhǔn)定位
CLAccuracyAuthorizationReducedAccuracy, // 模糊定位
};
- @property(weak, nonatomic, nullable) id<CLLocationManagerDelegate> delegate;
定位的代理實(shí)例,定位狀態(tài)的變化會(huì)在CLLocationManagerDelegate的方法中回調(diào)
- @property(assign, nonatomic) BOOL pausesLocationUpdatesAutomatically
指定定位是否會(huì)被系統(tǒng)自動(dòng)暫停带迟,默認(rèn)是YES
- @property(assign, nonatomic) BOOL allowsBackgroundLocationUpdates
是否允許后臺(tái)定位音羞,默認(rèn)是NO
- requestWhenInUseAuthorization
申請(qǐng)使用期間定位模式,下面會(huì)詳細(xì)解釋
- (void)requestAlwaysAuthorization
申請(qǐng)始終定位模式仓犬,下面會(huì)詳細(xì)解釋
四嗅绰、使用期間定位模式
- 需要在Info.plist中配置
NSLocationWhenInUseUsageDescription
; - 調(diào)用方法
requestWhenInUseAuthorization
申請(qǐng)使用期間定位模式,必須在status = kCLAuthorizationStatusNotDetermined
的時(shí)候搀继,調(diào)用才會(huì)出現(xiàn)系統(tǒng)彈窗窘面,否則無(wú)響應(yīng); - APP必須在前臺(tái)運(yùn)行時(shí)才會(huì)顯示系統(tǒng)彈窗
- 系統(tǒng)彈窗選項(xiàng):
選項(xiàng) | 授權(quán) |
---|---|
使用App時(shí)允許 | APP使用時(shí)授權(quán),不會(huì)失效status = WhenInUse |
允許一次 | 臨時(shí)授權(quán)叽躯,授權(quán)后status = WhenInUse 财边,下次再次啟動(dòng)App時(shí)授權(quán)會(huì)失效 status = notDetermined |
不允許 | 拒絕授權(quán),不允許授權(quán)請(qǐng)求status = Denied |
- 當(dāng)應(yīng)用程序在前臺(tái)開(kāi)啟正常使用時(shí)定位權(quán)限后点骑,如果在Xcode中開(kāi)啟后臺(tái)定位刷新的能力酣难,定位服務(wù)仍然可以在后臺(tái)繼續(xù)運(yùn)行;
- 當(dāng)應(yīng)用程序切換到具有后臺(tái)位置更新服務(wù)的后臺(tái)時(shí)黑滴,系統(tǒng)會(huì)在狀態(tài)欄中顯示藍(lán)色位置服務(wù)指示器憨募,表示定位仍在進(jìn)行中;
在iOS 16及更高版本中跷跪,主動(dòng)跟蹤用戶位置或最近啟用核心位置的應(yīng)用程序會(huì)在Control Center中顯示一個(gè)指示器馋嗜。
- 之后如果還需要定位齐板,則需要自己彈窗提醒用戶吵瞻。
五葛菇、始終定位模式
- 需要在Info.plist中配置
NSLocationAlwaysAndWhenInUseUsageDescription
、NSLocationWhenInUseUsageDescription
如果需要支持 iOS10 的話需要配置NSLocationAlawaysUsageDescription
橡羞; - 可以在授權(quán)狀態(tài)為
notDetermined
和whenInUse
時(shí)可調(diào)用requestAlwaysAuthorization
眯停; - 系統(tǒng)對(duì)
requestAlwaysAuthorization
方法的調(diào)用是有一定的限制的,當(dāng)APP調(diào)用此方法后卿泽,在繼續(xù)進(jìn)一步調(diào)用是無(wú)響應(yīng)的莺债,也就是說(shuō)不可以連續(xù)調(diào)用; - 授權(quán)方式
A签夭、 先獲取"使用期間定位"模式后齐邦,再申請(qǐng)"始終定位"權(quán)限
????獲取Always
權(quán)限前應(yīng)用程序需要先獲取到whenInUse
權(quán)限,然后再請(qǐng)求Always
授權(quán)第租。
????1措拇、如果APP在獲取whenInUse
權(quán)限后,立即調(diào)用requestAlwaysAuthorization方法慎宾,系統(tǒng)會(huì)立即提示用戶是否授權(quán)Always
權(quán)限或保持whenInUse
權(quán)限丐吓。
????2、如果用戶選擇”僅允許一次“授權(quán)后趟据,則系統(tǒng)會(huì)忽略requestAlwaysAuthorization
方法的任何調(diào)用券犁,此時(shí)屬于臨時(shí)授權(quán)狀態(tài)。
選項(xiàng) | 授權(quán) |
---|---|
保持僅使用期間 | 定位權(quán)限將繼續(xù)保持為使用期間定位汹碱,代理未收到任何回調(diào)status = WhenInUse |
更改為始終允許 | 定位權(quán)限將修改為始終定位粘衬,代理會(huì)收到狀態(tài)變化回調(diào)status = authorizedAlways |
當(dāng) status = notdetermined時(shí),調(diào)用requestWhenInUseAuthorization咳促,只有用戶同意“使用App時(shí)允許”的情況下才有用色难,然后當(dāng) status = WhenInUse時(shí),調(diào)用requestAlwaysAuthorization或系統(tǒng)查覺(jué)到APP需要”始終“定位時(shí)等缀,會(huì)再次出現(xiàn)始終授權(quán)模式彈窗枷莉。
B、直接申請(qǐng)獲取"始終定位"權(quán)限
如果APP在定位授權(quán)狀態(tài)為notDetermined
時(shí)尺迂,此時(shí)調(diào)用requestAlwaysAuthorization
方法后笤妙,系統(tǒng)會(huì)出現(xiàn)兩次彈窗。
1噪裕、第一次彈窗與申請(qǐng)”使用期間定位“權(quán)限時(shí)相同蹲盘;但是選擇”使用App時(shí)允許“意義有所不同
選項(xiàng) | 授權(quán) |
---|---|
使用App時(shí)允許 | APP獲得臨時(shí)的”始終“定位權(quán)限,status = authorizedAlways |
允許一次 | 臨時(shí)授權(quán)膳音,授權(quán)后status = WhenInUse 召衔,下次再次啟動(dòng)App時(shí)授權(quán)會(huì)失效 status = notDetermined |
不允許 | 拒絕授權(quán),不允許授權(quán)請(qǐng)求status = Denied |
2祭陷、第二次彈窗的時(shí)機(jī):
- 當(dāng)系統(tǒng)準(zhǔn)備向APP傳遞的事件需要authorizedAlways權(quán)限時(shí)苍凛;
- 如果APP處于臨時(shí)”始終“定位狀態(tài)時(shí)趣席;
- 當(dāng)APP進(jìn)入后臺(tái)進(jìn)入非活躍狀態(tài)掛起時(shí);
選項(xiàng) | 授權(quán) |
---|---|
保持僅使用期間 | 系統(tǒng)將授權(quán)由臨時(shí)”始終“更改為”使用期間“醇蝴,代理會(huì)收到狀態(tài)變化事件宣肚,status = WhenInUse |
更改為始終允許 | 移除臨時(shí)”始終”定位權(quán)限,變?yōu)椤笆冀K”授權(quán)狀態(tài)悠栓,代理不會(huì)會(huì)收到狀態(tài)變化回調(diào)霉涨,status = authorizedAlways |
注:如果用戶在提示出現(xiàn)后做出選擇,并選擇允許“始終”權(quán)限惭适,則位置事件將發(fā)送到您的應(yīng)用程序笙瑟。
六、確定應(yīng)用需要的授權(quán)限
A癞志、應(yīng)用程序的定位授權(quán)狀態(tài)決定了其是否需要及何時(shí)接收定位事件:
- When In Use(APP使用期間定位)
您的應(yīng)用程序可以在使用中使用所有位置服務(wù)并接收事件逮走。一般來(lái)說(shuō),如果iOS應(yīng)用程序位于前臺(tái)或在后臺(tái)運(yùn)行今阳,并且后臺(tái)位置使用指示器已啟用师溅,則視為正在使用。 - Always(APP總是定位)
您的應(yīng)用程序可以使用所有位置服務(wù)并接收事件盾舌,即使用戶不知道您的應(yīng)用程序正在運(yùn)行墓臭。如果你的應(yīng)用程序未運(yùn)行,系統(tǒng)將啟動(dòng)你的應(yīng)用程序并傳遞事件妖谴。 - “使用期間定位”是首選模式
B窿锉、盡可能的請(qǐng)求授權(quán)使用“使用期間定位”模式,此模式具有強(qiáng)大的功能膝舅,允許您的應(yīng)用程序:
1嗡载、在用戶使用應(yīng)用程序時(shí)訪問(wèn)所有可用的位置服務(wù)。如果用戶停止使用你的應(yīng)用程序仍稀,任何未完成的請(qǐng)求都將掛起洼滚,直到用戶恢復(fù)使用你的應(yīng)用程序?yàn)橹梗艜?huì)恢復(fù)定位服務(wù)
2技潘、如果您在Xcode項(xiàng)目中啟用了后臺(tái)位置更新遥巴,即使在應(yīng)用程序進(jìn)入后臺(tái)后,也可以繼續(xù)獲取位置更新享幽。
3铲掐、使用位置通知觸發(fā)器啟動(dòng)。如果您的應(yīng)用程序可以依賴用戶的交互值桩,請(qǐng)?jiān)O(shè)置UNLocationNotificationTrigger
摆霉,以在用戶進(jìn)入相關(guān)區(qū)域時(shí)通知用戶。當(dāng)用戶點(diǎn)擊通知時(shí),系統(tǒng)啟動(dòng)應(yīng)用程序携栋,使其有資格接收位置事件搭盾。此方法允許用戶在相關(guān)時(shí)刻決定是否與您的應(yīng)用程序共享其位置。
C刻两、當(dāng)應(yīng)用程序授權(quán)“使用期間定位”時(shí),如何確定應(yīng)用程序正在使用后定位滴某?
1磅摹、當(dāng)應(yīng)用程序在前臺(tái)運(yùn)行時(shí);
2霎奢、在應(yīng)用程序離開(kāi)前臺(tái)后進(jìn)入后的幾秒鐘內(nèi)户誓,您的應(yīng)用程序?qū)⒂幸粋€(gè)短的寬時(shí)間限期來(lái)完成用戶啟動(dòng)的任何當(dāng)前位置任務(wù);
3幕侠、當(dāng)應(yīng)用程序顯示后臺(tái)位置使用指示器(showsBackgroundLocationIndicator
)時(shí)帝美。在iOS上,指示燈是屏幕頂部的藍(lán)色條或小球晤硕;
D悼潭、請(qǐng)求"始終"授權(quán):
在以下情況下,您可能需要請(qǐng)求始終授權(quán):
1舞箍、您的應(yīng)用程序執(zhí)行自動(dòng)任務(wù)舰褪,在此期間可能會(huì)不方便或不需要的顯示提示;
2疏橄、你的應(yīng)用程序記錄了一天中的許多位置占拍,例如日記應(yīng)用程序。用戶可能更傾向于允許始終授權(quán)捎迫,以便您的應(yīng)用程序即使在未使用時(shí)也可以記錄位置晃酒,而無(wú)需提示用戶;
請(qǐng)記住窄绒,請(qǐng)求授權(quán)并不能保證你的應(yīng)用程序會(huì)收到授權(quán)贝次。如果您請(qǐng)求“始終定位”授權(quán),則用戶可以選擇在使用時(shí)授予您的應(yīng)用程序授權(quán)彰导。您必須始終準(zhǔn)備好在使用授權(quán)時(shí)運(yùn)行浊闪。
注:如果您的應(yīng)用程序已經(jīng)授權(quán)“使用時(shí)定位”授權(quán),您可以稍后單獨(dú)請(qǐng)求
Always authorization螺戳。然而搁宾,應(yīng)用程序可能只發(fā)出一個(gè)始終授權(quán)請(qǐng)求。
七倔幼、結(jié)束語(yǔ)
經(jīng)過(guò)分析和驗(yàn)證試驗(yàn)盖腿,確定在我的APP中定位回調(diào)異常問(wèn)題是因?yàn)檎?qǐng)求授權(quán)方式使用錯(cuò)誤,優(yōu)先使用When In Use
定位模式,然后在需要使用Always”
定位權(quán)限的位置再申請(qǐng)權(quán)限翩腐。當(dāng)APP得到定位模式被用戶選擇為“When In Use”時(shí)鸟款,進(jìn)入后臺(tái)觀察左上角是否有定位指示器(藍(lán)色圖標(biāo)),存在的話可以確定當(dāng)前定位服務(wù)正常茂卦。如果選擇Always
模糊何什,那么屏幕左上角會(huì)顯示定位圖標(biāo)。