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

版權(quán)聲明:本文來自書生依舊的簡書,轉(zhuǎn)載請注明出處 。

一. 運行時權(quán)限適配前

  1. 什么時候會觸發(fā)運行時權(quán)限機制?

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

  2. 觸發(fā)了運行時權(quán)限,沒有進行適配會怎么樣?

    應用崩潰。

  3. 來不及適配怎么辦?

    設(shè)置 targetSdkVersion < 23,會和以前一樣,在應用安裝申請所有的權(quán)限。值得注意的是用戶依然可以在設(shè)置里取消已授權(quán)的權(quán)限,這時候應用雖然不會崩潰,但是肯定是無法使用這個權(quán)限的,而且不會給用戶任何的提示。

二. 權(quán)限組

  • Android 將不同的權(quán)限分組管理,任何權(quán)限都會屬于一個權(quán)限組,包括正常權(quán)限和危險權(quán)限。
  • 應用申請危險權(quán)限時,系統(tǒng)會向用戶顯示一個對話框,描述應用要訪問的權(quán)限組,而不是不描述要申請的具體權(quán)限。一個權(quán)限組有一個權(quán)限申請成功,則默認該權(quán)限組所有權(quán)限申請成功,再次申請該組其他權(quán)限時,系統(tǒng)將立即授予該權(quán)限,不會再顯示申請權(quán)限的對話框。
  • 危險權(quán)限共 9 組 24 個
權(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
   // 檢查某個權(quán)限是否已授權(quán)
   ActivityCompat.checkSelfPermission(Context context, String permission)  
   // permission:要檢查的權(quán)限
   // 返回值是 int 類型,PackageManager#PERMISSION_GRANTED 表示有權(quán)限,PackageManager#PERMISSION_DENIED 表示沒有權(quán)限
  1. requestPermissions
   // 申請權(quán)限
   ActivityCompat.requestPermissions(final @NonNull Activity activity, final @NonNull String[] permissions, final @IntRange(from = 0) int requesPackageManager#PERMISSION_GRANTEDtCode)
   // permissions:要申請的權(quán)限,可以一次申請多個
   // requestCode:請求碼,在申請權(quán)限的回調(diào)中用到
  • 調(diào)用這個方法必然會走 onRequestPermissionsResult 的回調(diào)。
  1. onRequestPermissionsResult
   // 申請權(quán)限的回調(diào),在 Activity 和 Fragment 中都有
   onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
   // requestCode:requestPermissions 的參數(shù),請求碼
   // permissions:請求授權(quán)的權(quán)限,是一個數(shù)組,對應我們前面申請的多個權(quán)限
   // grantResults:授權(quán)結(jié)果,也是一個數(shù)組,對應上面每個權(quán)限的申請結(jié)果,PERMISSION_GRANTED 同意,PERMISSION_DENIED 拒絕
  1. shouldShowRequestPermissionRationale
   // 申請某個權(quán)限時我們是否要給用戶解釋一下
   ActivityCompat.shouldShowRequestPermissionRationale(@NonNull Activity activity, @NonNull String permission)
   // permission:要解釋的權(quán)限
  • 如果用戶拒絕過我們的權(quán)限申請,shouldShowRequestPermissionRationale 會返回 true。此時我們最好彈出一個對話框告訴用戶,你拒絕過我的權(quán)限申請,我申請這個權(quán)限是做什么用的,希望你能同意等等。
  • shouldShowRequestPermissionRationale 會返回 true 的時候,我們再次申請權(quán)限,會有一個 "不再提醒" 的 checkBox ,當用戶勾選上時,我們再次調(diào)用 shouldShowRequestPermissionRationale 會返回 false,意思說用戶都不想看到了,就沒有必要再解釋了。
  • 注意:用戶選擇 "不再提醒" 后,再次 requestPermissions 總是會失敗,但是會走 onRequestPermissionsResult 的回調(diào)。
  • 總結(jié):shouldShowRequestPermissionRationale 返回 false,有兩種可能,一是我們第一次申請權(quán)限的時候,二是用戶選擇了 "不再提醒"。shouldShowRequestPermissionRationale 返回 true 是用戶拒絕過我們的權(quán)限申請但是沒有勾選 "不再提醒"。

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

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

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

  3. 權(quán)限未申請,使用 requestPermissions 申請權(quán)限。

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

  5. 申請失敗使用 shouldShowRequestPermissionRationale 判斷用戶是否勾選了 "不再提醒"。

    • shouldShowRequestPermissionRationale 返回 fasle 勾選了的話,彈出一個 Dialog 引導用戶到設(shè)置界面授予權(quán)限,并在返回 Result 中再次判斷用戶是否同意權(quán)限,不同意的話怎給出提示。

      // 到設(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 這個庫
      RxActivityResult.on(context)
                      .startIntent(intent)
                      .subscribe(activityResult -> {
                         // 再次判斷用戶是否同意的權(quán)限,同意執(zhí)行后面的操作,不同給出提示。
                         checkPermission();
                      });
      

      ?

    • 沒有勾選,可以什么都不做,也可以彈出彈出一個 Dialog 引導用戶到設(shè)置界面授予權(quán)限。

五. 需要注意的地方

  • READ_PHONE_STATE、READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE 幾乎是必須的,可以放在啟動頁申請,用戶拒絕后引導至設(shè)置頁面。
  • 同時申請多個權(quán)限時,用戶可能僅僅同意某個權(quán)限,在 onRequestPermissionsResult 要循環(huán)判斷每個是否申請成功,然后進行后續(xù)的操作。

六. 推薦幾個類庫

兩個 star 比較多的運行時權(quán)限管理庫

  • RxPermissions

  • PermissionsDispatcher

    值得一說的是,第二個庫我在他的 issues 看到了解決了小米手機的相關(guān)問題(具體沒有去探究),第一個嘛,看名字也知道支持 RxJava 。

還有就是上文我使用的 RxActivityResult

Thanks

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

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容