Android 6.0 運(yùn)行時(shí)權(quán)限 總結(jié) & 實(shí)踐

版權(quán)聲明:本文來(lái)自書(shū)生依舊的簡(jiǎn)書(shū)劲藐,轉(zhuǎn)載請(qǐng)注明出處 氯窍。

一. 運(yùn)行時(shí)權(quán)限適配前

  1. 什么時(shí)候會(huì)觸發(fā)運(yùn)行時(shí)權(quán)限機(jī)制夺姑?

    targetSdkVersion >= 23 ,運(yùn)行在 Android 6.0 及以上設(shè)備上粘舟,使用 危險(xiǎn)權(quán)限 的時(shí)候。

  2. 觸發(fā)了運(yùn)行時(shí)權(quán)限承匣,沒(méi)有進(jìn)行適配會(huì)怎么樣蓖乘?

    應(yīng)用崩潰。

  3. 來(lái)不及適配怎么辦韧骗?

    設(shè)置 targetSdkVersion < 23嘉抒,會(huì)和以前一樣,在應(yīng)用安裝申請(qǐng)所有的權(quán)限袍暴。值得注意的是用戶(hù)依然可以在設(shè)置里取消已授權(quán)的權(quán)限些侍,這時(shí)候應(yīng)用雖然不會(huì)崩潰,但是肯定是無(wú)法使用這個(gè)權(quán)限的政模,而且不會(huì)給用戶(hù)任何的提示岗宣。

二. 權(quán)限組

  • Android 將不同的權(quán)限分組管理,任何權(quán)限都會(huì)屬于一個(gè)權(quán)限組淋样,包括正常權(quán)限和危險(xiǎn)權(quán)限耗式。
  • 應(yīng)用申請(qǐng)危險(xiǎn)權(quán)限時(shí),系統(tǒng)會(huì)向用戶(hù)顯示一個(gè)對(duì)話(huà)框趁猴,描述應(yīng)用要訪(fǎng)問(wèn)的權(quán)限組刊咳,而不是不描述要申請(qǐng)的具體權(quán)限。一個(gè)權(quán)限組有一個(gè)權(quán)限申請(qǐng)成功儡司,則默認(rèn)該權(quán)限組所有權(quán)限申請(qǐng)成功娱挨,再次申請(qǐng)?jiān)摻M其他權(quán)限時(shí),系統(tǒng)將立即授予該權(quán)限捕犬,不會(huì)再顯示申請(qǐng)權(quán)限的對(duì)話(huà)框跷坝。
  • 危險(xiǎn)權(quán)限共 9 組 24 個(gè)
權(quán)限組 權(quán)限
CALENDAR READ_CALENDAR WRITE_CALENDAR
CAMERA CAMERA
CONTACTS READ_CONTACTS WRITE_CONTACTS GET_ACCOUNTS
LOCATION ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION
MICROPHONE RECORD_AUDIO
PHONE READ_PHONE_STATE CALL_PHONE READ_CALL_LOG WRITE_CALL_LOG ADD_VOICEMAIL USE_SIP PROCESS_OUTGOING_CALLS
SENSORS BODY_SENSORS
SMS SEND_SMS RECEIVE_SMS READ_SMS RECEIVE_WAP_PUSH RECEIVE_MMS
STORAGE READ_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE

三. API 詳解

  1. checkSelfPermission
   // 檢查某個(gè)權(quán)限是否已授權(quán)
   ActivityCompat.checkSelfPermission(Context context, String permission)  
   // permission:要檢查的權(quán)限
   // 返回值是 int 類(lèi)型,PackageManager#PERMISSION_GRANTED 表示有權(quán)限碉碉,PackageManager#PERMISSION_DENIED 表示沒(méi)有權(quán)限
  1. requestPermissions
   // 申請(qǐng)權(quán)限
   ActivityCompat.requestPermissions(final @NonNull Activity activity, final @NonNull String[] permissions, final @IntRange(from = 0) int requesPackageManager#PERMISSION_GRANTEDtCode)
   // permissions:要申請(qǐng)的權(quán)限柴钻,可以一次申請(qǐng)多個(gè)
   // requestCode:請(qǐng)求碼,在申請(qǐng)權(quán)限的回調(diào)中用到
  • 調(diào)用這個(gè)方法必然會(huì)走 onRequestPermissionsResult 的回調(diào)垢粮。
  1. onRequestPermissionsResult
   // 申請(qǐng)權(quán)限的回調(diào)顿颅,在 Activity 和 Fragment 中都有
   onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
   // requestCode:requestPermissions 的參數(shù),請(qǐng)求碼
   // permissions:請(qǐng)求授權(quán)的權(quán)限,是一個(gè)數(shù)組粱腻,對(duì)應(yīng)我們前面申請(qǐng)的多個(gè)權(quán)限
   // grantResults:授權(quán)結(jié)果庇配,也是一個(gè)數(shù)組,對(duì)應(yīng)上面每個(gè)權(quán)限的申請(qǐng)結(jié)果绍些,PERMISSION_GRANTED 同意捞慌,PERMISSION_DENIED 拒絕
  1. shouldShowRequestPermissionRationale
   // 申請(qǐng)某個(gè)權(quán)限時(shí)我們是否要給用戶(hù)解釋一下
   ActivityCompat.shouldShowRequestPermissionRationale(@NonNull Activity activity, @NonNull String permission)
   // permission:要解釋的權(quán)限
  • 如果用戶(hù)拒絕過(guò)我們的權(quán)限申請(qǐng),shouldShowRequestPermissionRationale 會(huì)返回 true柬批。此時(shí)我們最好彈出一個(gè)對(duì)話(huà)框告訴用戶(hù)啸澡,你拒絕過(guò)我的權(quán)限申請(qǐng),我申請(qǐng)這個(gè)權(quán)限是做什么用的氮帐,希望你能同意等等嗅虏。
  • shouldShowRequestPermissionRationale 會(huì)返回 true 的時(shí)候,我們?cè)俅紊暾?qǐng)權(quán)限上沐,會(huì)有一個(gè) "不再提醒" 的 checkBox 皮服,當(dāng)用戶(hù)勾選上時(shí),我們?cè)俅握{(diào)用 shouldShowRequestPermissionRationale 會(huì)返回 false参咙,意思說(shuō)用戶(hù)都不想看到了龄广,就沒(méi)有必要再解釋了。
  • 注意:用戶(hù)選擇 "不再提醒" 后蕴侧,再次 requestPermissions 總是會(huì)失敗择同,但是會(huì)走 onRequestPermissionsResult 的回調(diào)。
  • 總結(jié):shouldShowRequestPermissionRationale 返回 false净宵,有兩種可能敲才,一是我們第一次申請(qǐng)權(quán)限的時(shí)候,二是用戶(hù)選擇了 "不再提醒"择葡。shouldShowRequestPermissionRationale 返回 true 是用戶(hù)拒絕過(guò)我們的權(quán)限申請(qǐng)但是沒(méi)有勾選 "不再提醒"紧武。

四. 權(quán)限適配最佳套路

  1. 在 AndroidManifest.xml 添加權(quán)限聲明。

  2. 使用 checkSelfPermission 檢查某個(gè)權(quán)限是否已經(jīng)申請(qǐng)刁岸。

  3. 權(quán)限未申請(qǐng)脏里,使用 requestPermissions 申請(qǐng)權(quán)限她我。

  4. 在 onRequestPermissionsResult 回調(diào)中判斷權(quán)限是否申請(qǐng)成功虹曙。

  5. 申請(qǐng)失敗使用 shouldShowRequestPermissionRationale 判斷用戶(hù)是否勾選了 "不再提醒"。

    • shouldShowRequestPermissionRationale 返回 fasle 勾選了的話(huà)番舆,彈出一個(gè) Dialog 引導(dǎo)用戶(hù)到設(shè)置界面授予權(quán)限酝碳,并在返回 Result 中再次判斷用戶(hù)是否同意權(quán)限,不同意的話(huà)怎給出提示恨狈。

      // 到設(shè)置界面授予權(quán)限
      Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
      Uri uri = Uri.fromParts("package",getPackageName(), null);
      intent.setData(uri);
      
      // startActivityForResult(intent);
      // 我這里使用的是 RxActivityResult 這個(gè)庫(kù)
      RxActivityResult.on(context)
                      .startIntent(intent)
                      .subscribe(activityResult -> {
                         // 再次判斷用戶(hù)是否同意的權(quán)限疏哗,同意執(zhí)行后面的操作,不同給出提示禾怠。
                         checkPermission();
                      });
      

      ?

    • 沒(méi)有勾選返奉,可以什么都不做贝搁,也可以彈出彈出一個(gè) Dialog 引導(dǎo)用戶(hù)到設(shè)置界面授予權(quán)限。

五. 需要注意的地方

  • READ_PHONE_STATE芽偏、READ_EXTERNAL_STORAGE雷逆、WRITE_EXTERNAL_STORAGE 幾乎是必須的,可以放在啟動(dòng)頁(yè)申請(qǐng)污尉,用戶(hù)拒絕后引導(dǎo)至設(shè)置頁(yè)面膀哲。
  • 同時(shí)申請(qǐng)多個(gè)權(quán)限時(shí),用戶(hù)可能僅僅同意某個(gè)權(quán)限被碗,在 onRequestPermissionsResult 要循環(huán)判斷每個(gè)是否申請(qǐng)成功某宪,然后進(jìn)行后續(xù)的操作。

六. 推薦幾個(gè)類(lèi)庫(kù)

兩個(gè) star 比較多的運(yùn)行時(shí)權(quán)限管理庫(kù)

  • RxPermissions

  • PermissionsDispatcher

    值得一說(shuō)的是锐朴,第二個(gè)庫(kù)我在他的 issues 看到了解決了小米手機(jī)的相關(guān)問(wèn)題(具體沒(méi)有去探究)兴喂,第一個(gè)嘛,看名字也知道支持 RxJava 包颁。

還有就是上文我使用的 RxActivityResult

Thanks

Android M 新的運(yùn)行時(shí)權(quán)限開(kāi)發(fā)者需要知道的一切

Android 6.0 運(yùn)行時(shí)權(quán)限處理完全解析

6.0運(yùn)行時(shí)權(quán)限的總結(jié)與實(shí)踐

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瞻想,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子娩嚼,更是在濱河造成了極大的恐慌蘑险,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岳悟,死亡現(xiàn)場(chǎng)離奇詭異佃迄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)贵少,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)呵俏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人滔灶,你說(shuō)我怎么就攤上這事普碎。” “怎么了录平?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵麻车,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我斗这,道長(zhǎng)动猬,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任表箭,我火速辦了婚禮赁咙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己彼水,他們只是感情好崔拥,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著凤覆,像睡著了一般握童。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叛赚,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天澡绩,我揣著相機(jī)與錄音,去河邊找鬼俺附。 笑死肥卡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的事镣。 我是一名探鬼主播步鉴,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼璃哟!你這毒婦竟也來(lái)了氛琢?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤随闪,失蹤者是張志新(化名)和其女友劉穎阳似,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體铐伴,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撮奏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了当宴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畜吊。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖户矢,靈堂內(nèi)的尸體忽然破棺而出玲献,到底是詐尸還是另有隱情,我是刑警寧澤梯浪,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布捌年,位于F島的核電站,受9級(jí)特大地震影響驱证,放射性物質(zhì)發(fā)生泄漏延窜。R本人自食惡果不足惜恋腕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一抹锄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦伙单、人聲如沸获高。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)念秧。三九已至,卻和暖如春布疼,著一層夾襖步出監(jiān)牢的瞬間摊趾,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工游两, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留砾层,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓贱案,卻偏偏與公主長(zhǎng)得像肛炮,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宝踪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容