1. 程式人生 > 實用技巧 >《第一行程式碼》閱讀筆記(二十五)——PermissionsDispatcher(補充)

《第一行程式碼》閱讀筆記(二十五)——PermissionsDispatcher(補充)

PermissionsDispatcher是一個基於註解、幫助開發者簡單處理Android 6.0系統中的執行時許可權的開源庫。避免了開發者編寫大量繁瑣的樣板程式碼。

開源地址:https://github.com/hotchemi/PermissionsDispatcher
文件介紹:http://hotchemi.github.io/PermissionsDispatcher/

匯入依賴

implementation "org.permissionsdispatcher:permissionsdispatcher:4.7.0"
annotationProcessor "org.permissionsdispatcher:permissionsdispatcher-processor:4.7.0"

註解

注意:被註解的方法不能是私有方法。

@RuntimePermissions註解:這是必須使用的註解,用於標註在你想要申請許可權的Activity或者Fragment上

@RuntimePermissions
public class SettingsActivity{

@NeedsPermission註解:這也是必須使用的註解,用於標註在你要獲取許可權的方法,註解括號裡面有引數,傳入想要申請的許可權。也就是說你獲取了相應的許可權之後就會執行這個方法。

  @NeedsPermission(Manifest.permission.CALL_PHONE)
    void makeCall() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
            Intent intent = new Intent(Intent.ACTION_DIAL);
            Uri data = Uri.parse("tel:" + getResources().getString(R.string.hot_line_phone_number));
            intent.setData(data);
            startActivity(intent);
        }
    }

這裡需要申請電話許可權,如果使用者同意了,就打電話。
還可以多個許可權一起申請。

    //獲取多個許可權
    @NeedsPermission({Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO})
    public void getMulti() {
        Toast.makeText(this, "getMulti", Toast.LENGTH_SHORT).show();
    }

這兩個註解是必須使用的,剩下的註解都不是必須選用的。

@OnShowRationale註解:這個不是必須的註解,用於標註申請許可權前需要執行的方法,註解
括號裡面有引數,傳入想要申請的許可權,而且這個方法還要傳入一個PermissionRequest物件,這個物件有兩種方法:proceed()讓許可權請求繼續,cancel()讓請求中斷。也就是說,這個方法會攔截你發出的請求,這個方法用於告訴使用者你接下來申請的許可權是幹嘛的,說服使用者給你許可權。

 @OnShowRationale({Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO})
    //給使用者解釋要請求什麼許可權,為什麼需要此許可權
    void showRationale(final PermissionRequest request) {
        new AlertDialog.Builder(this)
                .setMessage("使用此功能需要WRITE_EXTERNAL_STORAGE和RECORD_AUDIO許可權,下一步將繼續請求許可權")
                .setPositiveButton("下一步", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        request.proceed();//繼續執行請求
                    }
                }).setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        request.cancel();//取消執行請求
                    }
                }).show();
    }

request.proceed(); 調出系統申請許可權的彈窗會執行@NeedsPermissio對應的方法
request.cancel(); 會執行@OnPermissionDenied對應的方法

@OnPermissionDenied註解:這個也不是必須的註解,用於標註如果許可權請求失敗,但是使用者沒有勾選不再詢問的時候執行的方法,註解括號裡面有引數,傳入想要申請的許可權。也就是說,我們可以在這個方法做申請許可權失敗之後的處理,如像使用者解釋為什麼要申請,或者重新申請操作等。

    @OnPermissionDenied({Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO})//一旦使用者拒絕了
    public void multiDenied() {
        Toast.makeText(this, "已拒絕一個或以上許可權", Toast.LENGTH_SHORT).show();
    }
 
 
    @OnPermissionDenied(Manifest.permission.WRITE_EXTERNAL_STORAGE)//一旦使用者拒絕了
    public void StorageDenied() {
        Toast.makeText(this, "已拒絕WRITE_EXTERNAL_STORAGE許可權", Toast.LENGTH_SHORT).show();
    }

@OnNeverAskAgain註解:這個也不是必須的註解,用於標註如果許可權請求失敗,而且使用者勾選不再詢問的時候執行的方法,註解括號裡面有引數,傳入想要申請的許可權。也就是說,我們可以在這個方法做申請許可權失敗並選擇不再詢問之後的處理。例如,可以告訴作者想開啟許可權的就從手機設定裡面開啟。

注意,有些系統的不再詢問勾選項是要使用者拒絕授權一次才顯示出來的。

 
    @OnNeverAskAgain({Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO})//使用者選擇的不再詢問
    public void multiNeverAsk() {
        Toast.makeText(this, "已拒絕一個或以上許可權,並不再詢問", Toast.LENGTH_SHORT).show();
    }
    @OnNeverAskAgain(Manifest.permission.WRITE_EXTERNAL_STORAGE)//使用者選擇的不再詢問
    public void StorageNeverAsk() {
        Toast.makeText(this, "已拒絕WRITE_EXTERNAL_STORAGE許可權,並不再詢問", Toast.LENGTH_SHORT).show();
    }

解讀

使用PermissionsDispatcher除了要實現註解之外,還要重寫Activity的onRequestPermissionsResult()方法,在裡面讓一個PermissionsDispatcher執行回撥。

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

這個庫會自動生成[Activity Name] + PermissionsDispatcher這樣的一個類。當要呼叫使用許可權的方法的時候,不直接呼叫我們直接添加了@NeedsPermission的方法,而是呼叫這個類生成的XXXWithCheck的方法。XXX就是添加了@NeedsPermission的方法名。

這個PermissionsDispatcher是什麼來的呢?
  
原來只要我們實現了@RuntimePermissions和@NeedsPermission這兩個必須的註解之後,再build一次project之後,編譯器就會在在app\build\intermediates\classes\debug目錄下與被註解的Activity同一個包下這個庫會自動生成[Activity Name] + PermissionsDispatcher這樣的一個類。

switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
                StudentChallengeActivityPermissionsDispatcher.startRecordWithCheck(StudentChallengeActivity.this,img);
    }

用來呼叫被註解的Activity的方法(就是因為這個所以被註解的方法不能private,private方法的作用域不在其他的類)。所以,第一次用的話,要註解好之後,build一次,下面的方法裡面的PermissionsDispatcherActivityPermissionsDispatcher才不會令AS報紅。

外掛

AndroidStudio中還為我們提供了自動化生成工具。

只要在setting設定裡的plugins介面裡搜尋PermissionsDispatcher就可以安裝了,安裝完重啟一下就能使用:

  • 在所需的Activity或者Fragment的程式碼裡面右鍵,選擇Generate,然後就可以選擇Generate Runtime Permissions…(生成動態許可權的生成)或者下面的Add PermissionsDispatcher dependencies(新增PermissionsDispatcher依賴)

點選Generate Runtime Permissions…即可自動生成,很簡單粗暴。

參考文獻:
PermissionsDispatcher使用詳解
使用PermissionsDispatcher輕鬆解決Android許可權問題