Android權限申請


一、基本介紹

1、正常權限(安裝時權限):

不會直接給用戶隱私權帶來風險。如果您的應用在其清單中列出了正常權限,系統將自動授予該權限。

例如,設置時區的權限就是正常權限。如果應用聲明其需要正常權限,系統會自動向應用授予該權限。

2、危險權限(運行時權限):

會授予應用訪問用戶機密數據的權限。如果您列出了危險權限,則用戶必須明確批准您的應用使用這些權限。

3、注意:

  1. 在 Android 5.1(API 22)或更低版本,並且應用的 targetSdkVersion 是 22 或更低版本,則系統會在安裝時要求用戶授予權限。(沿用之前的權限系統),也就是在程序安裝的時候程序會將所有需要的權限全部列出來,其設計思路非常簡單,就是用戶如果認可你所申請的權限,那么就會安裝你的程序,如果不認可你所申請的權限,則會拒絕安裝。
  2. 從Android6.0版本開始才開始加入運行時權限,也就是說用戶不需要在安裝軟件的時候一次性授權所有的權限,而是可以在軟件的使用過程中再對某一項權限進行申請使用,這就是運行時權限。
  3. 在請求權限時,系統只告訴用戶應用需要的權限組,而不告知具體權限。(如上圖)

二、運行時權限(使用原生API)

1、步驟

  1. 首先要在清單文件中申請所需要的權限。

  2. 將硬件聲明為可選(uses-feature)以及要確定硬件可用性


3. 按API級別申明權限

當目標sdk大於等於29的時候配置android.permission.WRITE_EXTERNAL_STORAGE會出現下面的警報:

WRITE_EXTERNAL_STORAGE no longer provides write access when targeting Android 10+

這時候需要設置根據Api級別申明權限android:maxSdkVersion,該屬性表示設備搭載的系統版本高於 maxSdkVersion 時不需要特定權限。

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28"
        tools:ignore="ScopedStorage"/>
  1. 請求應用權限,其邏輯應該如下圖所示

  2. 首先檢查是否已經授予了某個權限,使用 ContextCompat.checkSelfPermission()此方法會返回 PERMISSION_GRANTEDPERMISSION_DENIED。如果 ContextCompat.checkSelfPermission() 方法返回 PERMISSION_DENIED,請調用 shouldShowRequestPermissionRationale()。如果此方法返回 true,請向用戶顯示指導界面,在此界面中說明用戶希望啟用的功能為何需要特定權限。(返回true說明應用之前請求過此權限但用戶拒絕了請求,此方法將返回 true),之后再調用requestPermissions函數進行權限的請求,這個函數會引起onRequestPermissionsResult的回調。

        private void callPhone(){
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
                    != PackageManager.PERMISSION_GRANTED) {
                // 應用沒有授予撥打電話權限,請求權限
                requestPhoneCallPermission();
            } else {
                // 應用被授予撥打電話權限 PackageManager.PERMISSION_GRANTED
                makeCall();
            }
        }
    
    private void requestPhoneCallPermission() {
            // 如果應用之前請求過此權限但用戶拒絕了請求,此方法將返回 true
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)){
                // 向用戶詳細解釋申請該權限的原因
                new AlertDialog.Builder(this)
                        .setCancelable(false)
                        .setMessage("撥打電話需要使用電話權限,如果不授予權限會導致該功能無法正常使用")
                        .setPositiveButton("好的", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ActivityCompat.requestPermissions(
                                        MainActivity.this,
                                        new String[]{Manifest.permission.CALL_PHONE},
                                        REQUEST_CALLPHONE//注意這個REQUEST_CALLPHONE會傳給回調函數的requestCode
                                );
                            }
                        })
                        .setNegativeButton("拒絕", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        })
                        .show();
            } else {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CALLPHONE);
            }
        }
    

    下面是回調函數:

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            if (requestCode == REQUEST_CALLPHONE) {
                if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // 授予權限,撥打電話
                    makeCall();
                } else {
                    Toast.makeText(this, "請求權限被拒絕", Toast.LENGTH_SHORT).show();
                }
            } else {
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
    

2、結果展示

當需要打電話的時候第一次請求:

當點擊禁止之后:
當再一次點擊打電話按鈕時:
點擊好的(又會看見請求權限的彈窗)
點擊始終允許后,直接把電話打了過去

三、運行時權限(使用PermissionsDispatcher)

該工具直接使用注解來自動幫我們生成權限請求代碼,使用時需要在項目中添加如下兩個注解:

    implementation "com.github.permissions-dispatcher:permissionsdispatcher:4.8.0"
    annotationProcessor "com.github.permissions-dispatcher:permissionsdispatcher-processor:4.8.0"
注解 是否必須 作用
@RuntimePermissions 這是必須使用的注解,標記Activity/Fragment,則注解解釋器會生成對應類的代碼
@NeedsPermission 標記需要請求使用權限的方法,也就是說你獲取了相應的權限之后就會執行這個方法,可以在括號里面加一個權限或者多個權限。
@OnShowRationale 對應之前的shouldShowRequestPermissionRationale(),當應用之前請求過此權限但用戶拒絕了請求,再次請求時調用,告知用戶為什么必須要授權這個權限,注解括號里面有參數,傳入想要申請的權限,而且這個方法還要傳入一個PermissionRequest對象,這個對象有兩種方法:proceed()讓權限請求繼續,cancel()讓請求中斷。也就是說,這個方法會攔截你發出的請求,這個方法用於告訴用戶你接下來申請的權限是干嘛的,說服用戶給你權限。
@OnPermissionDenied 當請求權限遭拒絕時調用,可以告知用戶已經拒絕該權限
@OnNeverAskAgain 當用戶勾選不再提示,並拒絕權限時,再次請求時調用(如上圖中禁止之后不再詢問按鈕)也就是說,我們可以在這個方法做申請權限失敗並選擇不再詢問之后的處理。例如,可以告訴作者想開啟權限的就從手機設置里面開啟。

注意:上面這些注解的方法都不能是private,原因看下面
使用PermissionsDispatcher除了要實現注解之外,還要重寫Activity的onRequestPermissionsResult()方法,在里面讓一個PermissionsDispatcher執行回調。這個PermissionsDispatcher是什么來的呢?

原來只要我們實現了@RuntimePermissions和@NeedsPermission這兩個必須的注解之后,再build一次project之后,編譯器就會在在app\build\intermediates\classes\debug目錄下與被注解的Activity同一個包下生成一個輔助類,名稱為 “被注解的Activity的名稱+PermissionsDispatcher” 的輔助類,用來調用被注解的Activity的方法(就是因為這個所以被注解的方法不能private,private方法的作用域不在其他的類)。所以,第一次用的話,要注解好之后,build一次,下面的方法里面的PermissionsDispatcherActivityPermissionsDispatcher才不會令AS報紅。

 @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionsDispatcherActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
    }

注意代碼中的onclick方法PermissionsDispatcherActivityPermissionsDispatchertakePhotoWithPermissionCheck方法在第一次編譯完成之后會自動生成。

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               PermissionsDispatcherActivityPermissionsDispatcher.takePhotoWithPermissionCheck(PermissionsDispatcherActivity.this);
            }
        });

上面的具體代碼鏈接:
https://github.com/Haoocker/Android_Learn/tree/master/RuntimePermissionDemo

參考閱讀

  1. https://developer.android.com/guide/topics/permissions/overview?hl=zh-cn
  2. https://www.jianshu.com/p/d6b3e16cc1d9
  3. https://github.com/permissions-dispatcher/PermissionsDispatcher
  4. https://blog.csdn.net/s13383754499/article/details/79034758


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM