1. 程式人生 > >Android 5.0 動態許可權申請的基本流程和套路

Android 5.0 動態許可權申請的基本流程和套路

注:本文主要是梳理一下Android動態許可權申請的一個基本套路。

需要有一定的Android編碼經驗,對於完全的新手來說,可能還有些技術細節沒有做具體解釋。

Android動態許可權申請有效保證了使用者的的安全,但是對開發者來說需要寫跟多的程式碼邏輯來跟使用者確認許可權。

先不考慮程式碼,我們通過官方文件的描述來梳理一下整個許可權處理的流程,如下圖:

從上圖可以看出,整個過程始於“許可權檢查”,歸集於“授權回撥”。

也就是說,除非本身就具備了相關許可權,否則我們所有的後續操作都需要從授權回撥開始往下走。

只是從授權回撥往下走的時候,需要根據前面流程所形成的的條件,進行不同的操作。

從圖中可以看出總共有三類分支(分別用紅、黃、綠三色標註):

1、使用者允許授權。

2、使用者禁止授權,且點選了“不再提示”複選框。

3、使用者禁止授權,但是沒有點選“不再提示”複選框。

那麼接下來我們就從這三種情況著手,將授權回撥的流程繼續梳理下去,如下圖:

按照谷歌的設計意圖,如果使用者拒絕了許可權,但是沒有選擇“不再提示”,我們就需要通過對話方塊等方式向用戶解釋為什麼需要授予許可權,然後再次申請許可權,彈出授權對話方塊。

如果使用者拒絕了許可權,而且選擇了“不再提示”,系統就不不會再彈出授權對話方塊。但是很多許可權都是APP執行的基本保證,所以我們還是得想辦法

解釋為什麼需要授權,然後引導使用者去授權。

我們可以看到,在授權回撥函式中時,只要是使用者使用者已經拒絕了許可權,我們都需要彈框向用戶進行許可權說明。

簡潔起見,我們完全可以把上圖中兩個自定義對話方塊的形態做到完全一樣,只是使用者點選授權後的授權不方式不一樣而已。

基於以上的完整流程分析,我們就可以設計出相應的程式碼。

 

此處以撥電話為例,先回顧一下上圖中谷歌的API:

1、檢測是否有許可權。

        // BEGIN 動態許可權申請程式碼段
        int hasCallPhonePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);
        if (hasCallPhonePermission == PackageManager.PERMISSION_GRANTED) {
            // 有許可權,執行相關操作
            callPhone();
        } else {
            // 無許可權,需要請求許可權
            ...
        }
        // END

2、請求許可權

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQ);

3、授權回撥

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == CALL_PHONE_REQ) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 使用者在授權對話方塊中授予了許可權,執行相關操作
                callPhone();
            } else {
                // 沒有授權
                if (ActivityCompat.shouldShowRequestPermissionRationale(
                        MainActivity.this, Manifest.permission.CALL_PHONE)) {
                    // 沒有點選“不再提示”
                    showPermissionDialog(FLAG_REQUEST_PERMISSION);
                } else {
                    // 點選了“不再提示”
                    showPermissionDialog(FLAG_SETTINGS_PERMISSION);
                }
            }
        }
    }

4、彈出包含說明的授權對話方塊。

    private void showPermissionDialog(final int flag) {
        new AlertDialog.Builder(this).setTitle("授權提示")
                .setMessage("需要授予撥打電話許可權才能打電話。")
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // 使用者取消了授權,整個路程結束,不執行任何操作。
                        Toast.makeText(MainActivity.this, "取消撥打電話", Toast.LENGTH_SHORT).show();
                    }
                })
                .setPositiveButton("去授權", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        switch (flag) {
                            case FLAG_REQUEST_PERMISSION:
                                // 使用者之前沒有點選“不再提示”,但是此處選在繼續授權的分支
                                // 請求系統授權對話方塊
                                ActivityCompat.requestPermissions(MainActivity.this,
                                        new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQ);
                                break;
                            case FLAG_SETTINGS_PERMISSION:
                                // 使用者之前點選過“不再提示”,此處選擇繼續授權的分支
                                // 到APP的詳情頁手動授權。
                                startActivity(getAppDetailSettingIntent());
                                break;
                        }

                    }
                }).create().show();
    }

5、跳轉到當前APP的應用詳情頁的Intent構造。

    private Intent getAppDetailSettingIntent() {
        Intent localIntent = new Intent();
        localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
        localIntent.setData(Uri.fromParts("package", getPackageName(), null));
        return localIntent;
    }

以上,與大家分享,希望能幫不太熟悉的朋友更清晰的梳理動態許可權申請的整個流程。