Android開發必知:6.0權限,官方分析

1.這個新的運行時權限僅當我們設置targetSdkVersion 23(這意味着你已經在23上測試通過了)才起作用,當然還要是M系統的手機。app在6.0之前的設備依然使用舊的權限系統。

如果app的targetSdkVersion 低於 23,那將被認爲app沒有用23新權限測試過,那將被繼續使用舊有規則:用戶在安裝的時候不得不接受所有權限,安裝後app就有了那些權限咯!然後app像以前一樣奔跑!注意,此時用戶依然可以取消已經同意的授權!用戶取消授權時,android 6.0系統會警告,但這不妨礙用戶取消授權。

問題又來了,這時候你的app崩潰嗎?

善意的主把這事也告訴了android小組,當我們在targetSdkVersion 低於23的app調用一個需要權限的函數時,這個權限如果被用戶取消授權了的話,不拋出異常。但是他將啥都不幹,結果導致函數返回值是null或者0.

2.代碼沒有成功改爲支持最新運行時權限的app,不要設置targetSdkVersion 23 發佈,否則你就有麻煩了。只有當你測試過了,再改爲targetSdkVersion 23 。
警告:現在你在android studio新建項目,targetSdkVersion 會自動設置爲 23。如果你還沒支持新運行時權限,我建議你首先把targetSdkVersion 降級到22

3.權限組:
同一組的任何一個權限被授權了,其他權限也自動被授權。例如,一旦WRITE_CONTACTS被授權了,app也有READ_CONTACTS和GET_ACCOUNTS了。

權限分組官方表格如下:
這裏寫圖片描述

下面我們來看具體的使用方法:

1.請求要申請的權限

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
    ActivityCompat.requestPermissions(this,
        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_PHONE_STATE},2);
}else {
    startActivity(new Intent(this,MainActivity.class));
    finish();
}

2.請求後的回調方法,根據返回的結果碼執行操作

//動態權限申請後系統的回調方法
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode){
        case MY_PERMISSIONS_REQUEST:
            for (int i = 0; i < grantResults.length; i++) {
                //檢查權限是否被拒絕
                                if(grantResults[i]==PackageManager.PERMISSION_DENIED) {
                    Toast.makeText(SplashActivity.this, "本應用需要申請讀寫sdcard權限來訪問本地文件", Toast.LENGTH_SHORT).show();
                    return;
                }
            }
            break;
    }
    Intent intent = new Intent(SplashActivity.this,MainActivity.class);
    startActivity(intent);
    finish();
}

3.要注意這個方法,用戶允許或拒絕返回值的類型

/**
 * 用戶第一次拒絕後,下一次,返回true,應該提示用戶爲什麼需要這個權限,添加說明
 * 用戶第二次請求權限時,用戶拒絕了,並選擇了不再提醒,返回false
 * 設備的策略禁止當前應用獲取這個權限的授權,返回false
 *
 * 注意:第二次請求權限時候纔有選項“不再提醒”,如果用戶一直拒絕,但沒有選擇不再提醒,下次請求權限時候,
 * 會繼續有不再提醒的權限
 */
@Override
public boolean shouldShowRequestPermissionRationale(String permission) {
    return super.shouldShowRequestPermissionRationale(permission);
}

以上就是Google官方的權限申請方法,這裏總結下實際使用時候需要的注意點:

1.只請求你需要的權限:減少請求的次數,或用intent來代替,讓其他的應用來處理。
防止一次請求太多的權限或請求次數太多,用戶可能對你的應用感到厭煩。

2.在應用啓動的時候,最好先請求應用必須的一些權限,不是必須的,在使用的時候,才請求(如一些附帶權限),需要自己整理,管理一下自己應用的權限分類:

2.1 普通權限(normal permissions):只需要在androidmanifest.xml中聲明相應的權限,在安裝應用時,會默認獲得許可。並且用戶不能修改權限許可。(只需要在AndroidManifest.xml中簡單聲明這些權限就好,安裝時就授權。不需要每次使用 時都檢查權限,而且用戶不能取消以上授權。)

2.2 需要申請的權限(dangerous permissions):

2.2.1 必要權限:最好在應用啓動的時候,進行請求許可的一些權限(主要是應用中主要功能需要的權限)
2.2.2 附帶權限:不是應用主要功能需要的權限(如:分享圖片時,需要讀取應用的通訊錄等等)

3.解釋你的應用爲什麼需要這些權限:在請求之前requestPermissions().,提示用戶,讓用戶不會感到困惑

4.Android 6.0運行時權限勾選不再詢問後該如何處理?

當第一次請求權限申請被拒絕後再進行第二次申請時,對話框中會多出一個 不再詢問 的複選框。如果勾選了該複選框並且拒絕請求,那麼以後將無法再申請該權限。也就是說在調用 requestPermissions() 後,onRequestPermissionsResult() 會立刻被調用並且申請結果爲 PERMISSION_DENIED 。 其實這個時候還是有一根救命稻草的。

判斷是否勾選不再詢問

 //首先需要判斷用戶是否勾選了不再詢問。
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case MY_PERMISSIONS_APPLY:
                for (int i = 0; i < grantResults.length; i++) {
                    //判斷權限的結果,如果有被拒絕,就return
                    if (grantResults[i] == PackageManager.PERMISSION_DENIED){
                        if (!ActivityCompat.shouldShowRequestPermissionRationale(this,
                                permissions[i])){
                            showToast("點擊權限,並打開全部權限");
                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                            Uri uri = Uri.fromParts("package", getPackageName(), null);
                            intent.setData(uri);
                            startActivityForResult(intent, REQUEST_PERMISSION_SETTING);
                    }
ActivityCompat 位於 support.v7 包中,因爲運行時權限是 6.0 的新特性,使用該類可以省略對版本的判斷當權限申請被拒絕並且shouldShowRequestPermissionRationale() 返回 false 就表示勾選了不再詢問。轉到設置界面現在我們唯一能做的就是跳轉到我們 App 的設置界面,讓用戶手動開啓權限了。
也就是這幾行代碼,上面已經貼出,方便大家參考:
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, REQUEST_PERMISSION_SETTING);

當然,你也可以先彈出對話框詢問用戶是否要授予權限,然後再跳轉。
跳轉到設置界面調用的是 startActivityForResult() 而不是 startActivity() 。
在 onActivityResult() 中沒有必要對 resultCode 進行判斷,因爲用戶只能通過返回鍵才能回到我們的 App 中,所以 resultCode 總是爲 RESULT_CANCEL。
在 onActivityResult() 中還需要對權限進行判斷,因爲用戶有可能沒有授權就返回了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章