Android 開發技巧 - Android 6.0 以上權限大坑和權限檢查基類封裝

shihunwudi 8年前發布 | 21K 次閱讀 安卓開發 Android開發 移動開發

簡單介紹

關于運行時權限的說法,早在Google發布android 6.0的時候,大家也聽得蠻多的。從用戶的角度來講,用戶是受益方,更好的保護用戶的意思,而對于開發者來說,無疑增加了工作量。

對于6.0以下的權限在安裝時,會根據權限聲明產生一個權限列表,用戶只有同意才能完成app的安裝。而在6.0以后,不需要先對權限授權就可以安裝app,對于權限的授權我們可以選擇禁止。

在新的權限機制中,Google將權限分為兩類:

Normal Permissions(普通權限):不涉及用戶隱私,不需要用戶進行授權,比如訪問網絡等;

Dangerous Permission(危險權限):涉及到用戶隱私,需要用戶進行授權,比如相機訪問、讀取SD卡等。

PS:運行時權限只適合APP運行在Android 6.x以上的機器,對于危險權限Google官方也對其進行了分組,只要一組中的某一權限被授權,同組的權限也同樣會被授權。

操作步驟

簡單的介紹了關于運行時權限的使用方法,操作步驟如下

  1. 在Androidmanifest.xml文件聲明相關權限

  2. 通過ContextCompat.checkSelfPermission方法檢查某項權限被授予情況

  3. 申請授權

  4. 權限回調處理

封裝調用

權限的申請我們一般的做法都在Activity被創建的時候,才開始申請危險權限。而每次都得重復上述的操作,想想都覺得煩。為此,筆者將運行時權限的使用進行了進一步的歸納總結。將權限的檢查統一封裝在基類中,子類繼承并實現抽象方法,傳入權限數組等即可。

1)通過抽象方法getNeedPermissions( )獲取需要進行檢測的權限數組,檢查相關權限是否授權,如果未授權則開始申請權限

/**

 * 檢查所有權限,無權限則開始申請相關權限
 */
protected void checkAllNeedPermissions() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
    List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
    if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) {
        ActivityCompat.requestPermissions(this, needRequestPermissonList.toArray(
                new String[needRequestPermissonList.size()]), REQUEST_CODE_PERMISSON);
    }
}</code></pre> 

2)權限授權情況回調處理,這里授權失敗默認彈框是否前往設置頁面授權

/**
     * 權限授權結果回調
     *
     * @param requestCode
     * @param permissions
     * @param paramArrayOfInt
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] paramArrayOfInt) {
        if (requestCode == REQUEST_CODE_PERMISSON) {
            if (!verifyPermissions(paramArrayOfInt)) {
                permissionGrantedFail();
                showTipsDialog();
                isNeedCheckPermission = false;
            } else permissionGrantedSuccess();
        }
    }

PS:其中permissionGrantedSuccess()和permissionGrantedSuccess()為抽象方法,由子類實現。

3)簡單調用,子類繼承該基類,實現以下抽象方法即可

@Override
    public String[] getNeedPermissions() {
        return new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
    }

    @Override
    protected void permissionGrantedSuccess() {

    }

    @Override
    protected void permissionGrantedFail() {
    }

有沒有覺得醬紫操作清晰了很多,也方便了不少。依然如此,就趕緊mark吧。

封裝類的完整代碼如下:

/**
 * Created by chenyk on 2016/9/28.
 * 檢查相關權限基類,適用于android 6.0 運行時權限
 * 使用方法:需要運行時權限的activity繼承此類
 */
public abstract class BaseCheckPermissionActivity extends NeedBackActivity
        implements OnRequestPermissionsResultCallback {
    private static final int REQUEST_CODE_PERMISSON = 2020; //權限請求碼

    private boolean isNeedCheckPermission = true; //判斷是否需要檢測,防止無限彈框申請權限

    @Override
    protected void onResume() {
        super.onResume();
        if (isNeedCheckPermission) {
            checkAllNeedPermissions();
        }
    }

    /**
     * 檢查所有權限,無權限則開始申請相關權限
     */
    protected void checkAllNeedPermissions() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
        List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
        if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) {
            ActivityCompat.requestPermissions(this, needRequestPermissonList.toArray(
                    new String[needRequestPermissonList.size()]), REQUEST_CODE_PERMISSON);
        }
    }

    /**
     * 獲取權限集中需要申請權限的列表
     *
     * @param permissions
     * @return
     */
    private List<String> getDeniedPermissions(String[] permissions) {
        List<String> needRequestPermissonList = new ArrayList<>();
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(this, permission) !=
                    PackageManager.PERMISSION_GRANTED ||
                    ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
                needRequestPermissonList.add(permission);
            }
        }
        return needRequestPermissonList;
    }

    /**
     * 所有權限是否都已授權
     *
     * @return
     */
    protected boolean isGrantedAllPermission() {
        List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
        return needRequestPermissonList.size() == 0;
    }

    /**
     * 權限授權結果回調
     *
     * @param requestCode
     * @param permissions
     * @param paramArrayOfInt
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] paramArrayOfInt) {
        if (requestCode == REQUEST_CODE_PERMISSON) {
            if (!verifyPermissions(paramArrayOfInt)) {
                permissionGrantedFail();
                showTipsDialog();
                isNeedCheckPermission = false;
            } else permissionGrantedSuccess();
        }
    }

    /**
     * 檢測所有的權限是否都已授權
     *
     * @param grantResults
     * @return
     */
    private boolean verifyPermissions(int[] grantResults) {
        for (int grantResult : grantResults) {
            if (grantResult != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    /**
     * 顯示提示對話框
     */
    protected void showTipsDialog() {
        new AlertDialog.Builder(this).setTitle("提示信息").setMessage("當前應用缺少" + getDialogTipsPart()
                + "權限,該功能暫時無法使用。如若需要,請單擊【確定】按鈕前往設置中心進行權限授權。")
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        finish();
                    }
                })
                .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        startAppSettings();
                    }
                }).show();
    }


    /**
     * 啟動當前應用設置頁面
     */
    private void startAppSettings() {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivity(intent);
    }

    /**
     * 獲取彈框提示部分內容
     *
     * @return
     */
    protected String getDialogTipsPart() {
        return "必要";
    }

    /**
     * 獲取需要進行檢測的權限數組
     */
    protected abstract String[] getNeedPermissions();

    /**
     * 權限授權成功
     */
    protected abstract void permissionGrantedSuccess();

    /**
     * 權限授權失敗
     */
    protected abstract void permissionGrantedFail();

 

 

 

來自:http://www.jianshu.com/p/a0ca49f7cb61

 

 本文由用戶 shihunwudi 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!