android權限處理詳解

寫在前面
對于android 6.0來說,增加了權限的管理,能夠更好的保護用戶的隱私,當用戶需要某權限時,才動態(tài)的去申請。用戶也可以在應用權限管理里面關閉和打開。為了方便以后使用,這里對權限使用相關做一個簡單的總結。

android權限分類

Android6.0系統(tǒng)把權限分為兩個級別:

  • Normal Permissions,即普通權限,這類權限不會潛藏有侵害用戶隱私和安全的問題,比如,訪問網(wǎng)絡的權限,訪問WIFI的權限等;
  • Dangerous Permissions,即危險權限,這類權限會直接的威脅到用戶的安全和隱私問題,比如說訪問短信,相冊等權限。

普通權限是不會威脅到用戶安全的,所以這類權限是可以直接在manifest里面直接的使用,而且在安裝后也會直接的生效了。不需要特殊處理。危險權限在使用時不僅需要在manifest里面注冊,還需要動態(tài)申請,否則程序會崩潰,提示沒有權限。
危險權限分為9組,總共24個權限,如下:

權限組名 權限名
CALENDAR 日歷 READ_CALENDAR
WRITE_CALENDER
CAMERA 相機 CAMERA
CONTACTS 聯(lián)系人 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 短信 Short Message Service
SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGE 數(shù)據(jù)存儲 READ_EXTRAL_STRORAGE
WRITE_EXTERNAL_STORAGE

申請權限時:
1、在清單文件中聲明權限(如果不在這張表中,聲明完就可以了)
2、如果在這張表中的權限需要手動來申請

這些權限6.0以后需要手動申請,,每一個權限組中的權限只要有一個權限同意授權了,整個權限組中的權限就不用重復申請了。
如果如果查看所有的權限,請參考:
https://developer.android.com/about/versions/marshmallow

android 權限使用場景

由于android 系統(tǒng)版本太多,并且用戶使用的手機版本也無法確定,因此在權限處理時,需要多方面考慮。 而對于開發(fā)者而言,最主要考慮的是 targetversion和buildVersion(即真機系統(tǒng)版本)。下面從以下方面考慮:

targetVersion BuildVersion 是否需要處理
>=23 >=23 需要動態(tài)處理
>=23 <23 不需要
< 23 >=23 需要處理
< 23 <23 不需要

權限基本使用

  1. 在manifest.xml文件中聲明需要的權限
  2. 檢查是否擁有權限,通過checkSelfPermission函數(shù),如下:
if (ContextCompat.checkSelfPermission(thisActivity,
            Manifest.permission.READ_CONTACTS)
    != PackageManager.PERMISSION_GRANTED) {
    //沒有授權,編寫申請權限代碼
}else{
//已經(jīng)授權,執(zhí)行操作代碼
}   

checkSelfPermission函數(shù)有兩個參數(shù):context和需要的權限

  1. 若沒有權限則申請權限,如下:
ActivityCompat.requestPermissions(thisActivity,
            new String[]{Manifest.permission.READ_CONTACTS},
            1);

這是一個異步的方法,第一個參數(shù)是Context;第二個參數(shù)是需要申請的權限的字符串數(shù)組(這個是支持同時申請多個權限,系統(tǒng)會逐個詢問是否授權);第三個參數(shù)為請求碼requestCode,主要用于回調(diào)的時候檢測。

  1. 處理權限的回調(diào)結果
  //權限回調(diào)方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode){

        case 0:
            //grantResults數(shù)組存儲的申請的返回結果,
            //PERMISSION_GRANTED 表示申請成功
            if (grantResults.length>0&&grantResults[0]== PackageManager.PERMISSION_GRANTED){
                //授權成功,
                //這里寫相應的 操作代碼
            }else{
                //授權失敗,可以簡單提示用戶
                Toast.makeText(this, "沒有授權繼續(xù)操作", Toast.LENGTH_SHORT).show();
            }
            break;
        default:
            break;
    }
}

注意:申請的時候是一個一個的申請的話,每次申請都有一個請求碼,這里的grantResults數(shù)組就只有一個值,所以都是grantResults[0]來和PERMISSION_GRANTED來進行比較
如果是一次申請多個權限,grantResults數(shù)組返回的值就不止一個,但是,直接遍歷它就行,只要全部滿足條件才算申請成功,才能進行相應的操作
一般的寫法是:
通過if判斷權限是否申請,沒有申請,把它加到一個集合里面,把所有的權限都判斷一遍以后,去遍歷這個集合,只要有一個沒有申請的,就需、要去申請權限, 把這個集合轉為數(shù)組,傳到requestPermissions的第二個參數(shù),然后就處理相應結果就可以了,遍歷grantResults數(shù)組,判斷是不是全部滿足條件

特殊處理

但 targetVersion小于23,但是BuildVersion大于23這個場景時,若用戶在應用權限設置里面手動關閉了要使用的權限,在應用操作時,檢查權限會一直返回true,并且系統(tǒng)崩潰。
導致這個的原因,是 ContextCompat.checkSelfPermission函數(shù)再TargetVersion<23時,會一直返回true。因此為了兼容此情形,V4包里面提供了PermissionChecker.checkSelfPermission函數(shù),用來處理這種情形。因此,考慮兩種情形,完成的權限檢查代碼如下:

 /**
     * android 6.0 以上檢查是否有權限
     * @param context    context
     * @param primission 權限名稱
     * @return false 沒有權限   true 有權限
     */
    private boolean checkPrimission(Context context ,String primission)
    {
        int targetSdkVersion ;
        boolean result = false;
        PackageInfo info = null;
        try {
            info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            targetSdkVersion = info.applicationInfo.targetSdkVersion;
            if (targetSdkVersion >= Build.VERSION_CODES.M) {  //targetSdkVersion >= 23
                if (ContextCompat.checkSelfPermission(cdActivity, primission) != PackageManager.PERMISSION_GRANTED) {
                    result = false;
                }else{
                    result = true;
                }
            } else { //targetSdkVersion < 23
                if (PermissionChecker.checkSelfPermission(cdActivity, Manifest.permission.CAMERA)
                        != PermissionChecker.PERMISSION_GRANTED) {
                    result = false;
                }else{
                    result = true;
                }
            }

        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG,e.getMessage());
        }


        return result;
    }

多次請求處理

shouldShowRequestPermissionRationale應用場景

//參數(shù)是一個權限,返回true或false
shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)

?當用戶第一次拒絕申請的權限,第二次再申請權限之前彈出一個對話框,給用戶做出一個解釋,為啥需要申請權限,根據(jù)用戶的選擇,再考慮是否申請權限。

該函數(shù)返回值根據(jù)不同情形有以下情況:
?1. 第一次請求某權限時,返回值為false
?2. 第一次請求某權限拒絕后,返回值為true
?3. 第二次請求某權限拒絕后,返回值為true
?4. 第三次請求某權限,點了不再提醒,并拒絕,返回值為false
?5. 任何時候,只要允許了權限,返回值就為false

因此根據(jù)這些情況可以做一下特殊處理

  • 在請求權限前,調(diào)用此函數(shù),判斷是否需要和用戶解釋(true,表示拒絕過一次);
  • 在onRequestPermissionsResult里面調(diào)用,判斷用戶是否點了“不在詢問”,并拒絕??梢詮棾鰧υ捒蛞龑в脩羧ピO置頁面設置。
    ??不再提醒權限方法:(用戶勾選拒絕后不再詢問)
//參數(shù)是一個權限,返回true或false
shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)
  • 返回true表示用戶沒有勾選 拒絕后不再詢問,你可以再去調(diào)用requestPermissions申請權限

  • 返回false分幾種情況:
    1.用戶勾選了 拒絕后不再詢問,你只能引導用戶去設置中開啟權限了
    2.用戶自己在設置中把權限給關了...
    3.系統(tǒng)禁止應用具有該權限!
    注意:部分手機會對權限有自己的默認處理,比如小米,該函數(shù)一直返回false,因此,針對于不同的手機需要自己適配處理該方法。

android 8.0 處理

??在android 6.0 之上,最開始的處理是: 只要一組權限中的一個權限通過,該組其他權限也默認通過。
??對于針對Android O的應用,此行為已被糾正。系統(tǒng)只會授予應用明確請求的權限。然而一旦用戶為應用授予某個權限,則所有后續(xù)對該權限組中權限的請求都將被自動批準。
例如,假設某個應用在其清單中列出READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE。應用請求READ_EXTERNAL_STORAGE,并且用戶授予了該權限,如果該應用針對的是API級別24或更低級別,系統(tǒng)還會同時授予WRITE_EXTERNAL_STORAGE,因為該權限也屬于STORAGE權限組并且也在清單中注冊過。如果該應用針對的是Android O,則系統(tǒng)此時僅會授予READ_EXTERNAL_STORAGE,不過在該應用以后申請WRITE_EXTERNAL_STORAGE權限時,系統(tǒng)會立即授予該權限,而不會提示用戶。

權限請求框架

  • RxPermission
  • PermissionsDispatcher
  • EasyPermissions
    具體使用方式后續(xù)補充??梢詆ithub上自行搜索使用方式。

自己也封裝過一個框架
github地址:https://github.com/YuanQiCan/PermissionGrant
包含以下功能:

  1. 權限檢查,targetSdkVersion 大于23和小于23兩種情形
  2. 單個權限和多個權限申請?zhí)幚?/li>
  3. shouldShowRequestPermissionRationale包含的情形處理
  4. 基本對畫框顯示和頁面跳轉

有興趣的可以看看,使用方便。

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

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

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