《android運行時權限處理》

權限在android6.0一個分水嶺。在6.0咱們只須要在AndroidManifest.xml文件中去申請權限,這個仍是有點簡單的相信你們都明白。而在6.0+則發生了變化。就是某些特殊的權限好比:定位、攝像等。其實這才符合人們的使用習慣,指哪打哪。java

既然說了指哪打哪就要咱們動態的去判斷一個權限和多個權限是否已經被受權或者沒有受權的狀況下是否須要彈出框。而ContextCompat中就有一個方法checkSelfPermission來專門來爲咱們服務,完成該項工做。具體代碼以下android

public class PermissionManager {
	
    private Object mObject;
    private String[] mPermissions;
    private int mRequestCode;
    private PermissionListener mListener;
    // 用戶是否確認瞭解釋框的
    private boolean mIsPositive = false;

    public static PermissionManager with(Activity activity) {
        return new PermissionManager(activity);
    }

    public static PermissionManager with(Fragment fragment) {
        return new PermissionManager(fragment);
    }

    public PermissionManager permissions(String... permissions) {
        this.mPermissions = permissions;
        return this;
    }

    public PermissionManager addRequestCode(int requestCode) {
        this.mRequestCode = requestCode;
        return this;
    }

    public PermissionManager setPermissionsListener(PermissionListener listener) {
        this.mListener = listener;
        return this;
    }

    public PermissionManager(Object object) {
        this.mObject = object;
    }

    /**請求權限  
     * @return PermissionManager  
     */
    public PermissionManager request() {
        request(mObject, mPermissions, mRequestCode);
        return this;
    }

    private void request(Object object, String[] permissions, int requestCode) {
        // 根據權限集合去查找是否已經受權過
        Map<String, List<String>> map = findDeniedPermissions(getActivity(object), permissions);
        List<String> deniedPermissions = map.get("deny");
        List<String> rationales = map.get("rationale");
        if (deniedPermissions.size() > 0) {
            // 第一次點擊deny才調用,mIsPositive是爲了防止點確認解釋框後調request()遞歸調onShowRationale
            if (rationales.size() > 0 && mIsPositive == false) {
                if (mListener != null ) {
                    mListener.onShowRationale(rationales.toArray(new String[rationales.size()]));
                }
                return;
            }
            if (object instanceof Activity) {
                ActivityCompat.requestPermissions((Activity) object, deniedPermissions.toArray(new String[deniedPermissions.size()]), requestCode);
            } else if (object instanceof Fragment) {
                ((Fragment) object).requestPermissions(deniedPermissions.toArray(new String[deniedPermissions.size()]), requestCode);
            } else {
                throw new IllegalArgumentException(object.getClass().getName() + " is not supported");
            }
        } else {
            if (mListener != null) {
                mListener.onGranted();
            }
        }
    }

    /**根據requestCode處理響應的權限
     * @param permissions
     * @param results   
     */
    public void onPermissionResult(String[] permissions, int[] results) {
        List<String> deniedPermissions = new ArrayList<String>();
        for (int i = 0; i < results.length; i++) {
            if (results[i] != PackageManager.PERMISSION_GRANTED) {//未受權
                deniedPermissions.add(permissions[i]);
            }
        }
        if (deniedPermissions.size() > 0) {
            if (mListener != null) {
                mListener.onDenied();
            }
        } else {
            if (mListener != null) {
                mListener.onGranted();
            }
        }
    }
    
    private Map<String, List<String>> findDeniedPermissions(Activity activity, String... permissions) {
        Map<String, List<String>> map = new HashMap<String, List<String>>();
        List<String> denyList = new ArrayList<String>();//未受權的權限
        List<String> rationaleList = new ArrayList<String>();//須要顯示提示框的權限
        for (String value : permissions) {
            if (ContextCompat.checkSelfPermission(activity, value) != PackageManager.PERMISSION_GRANTED) {
                denyList.add(value);
                if (shouldShowRequestPermissionRationale(value)) {
                    rationaleList.add(value);
                }
            }
        }
        map.put("deny", denyList);
        map.put("rationale", rationaleList);
        return map;
    }

    private Activity getActivity(Object object) {
        if (object instanceof Fragment) {
            return ((Fragment) object).getActivity();
        } else if (object instanceof Activity) {
            return (Activity) object;
        }
        return null;
    }

    /**
     * 當用戶拒絕某權限時並點擊就再也不提醒的按鈕時,下次應用再請求該權限時,須要給出合適的響應(好比給個展現對話框)
     * @param permission
     */
    private boolean shouldShowRequestPermissionRationale(String permission) {
        if (mObject instanceof Activity) {
            return ActivityCompat.shouldShowRequestPermissionRationale((Activity) mObject, permission);
        } else if (mObject instanceof Fragment) {
            return ((Fragment) mObject).shouldShowRequestPermissionRationale(permission);
        } else {
            throw new IllegalArgumentException(mObject.getClass().getName() + " is not supported");
        }
    }

    public void setIsPositive(boolean isPositive) {
        this.mIsPositive = isPositive;
    }
}

還有一個回調接口數組

public interface PermissionListener {
    /**
     * 用戶受權後調用
     */
    public void  onGranted();
    
    /**
     * 用戶禁止後調用
     */
    public void  onDenied();
    
    /**是否顯示闡述性說明
     * @param permissions 返回須要顯示說明的權限數組
     */
    public void onShowRationale(String[] permissions);
}

調用代碼:ide

PermissionManager helper;
helper = PermissionManager.with(MainActivity.this)
        //添加權限請求碼
        .addRequestCode(MainActivity.REQUEST_CODE_CAMERA)
        //設置權限,能夠添加多個權限
        .permissions(Manifest.permission.CAMERA)
        //設置權限監聽器
        .setPermissionsListener(new PermissionListener() {

            @Override
            public void onGranted() {
                //當權限被授予時調用
               Toast.makeText(MainActivity.this, "Camera Permission granted",Toast.LENGTH_LONG).show();
            }

            @Override
            public void onDenied() {
                //用戶拒絕該權限時調用
               Toast.makeText(MainActivity.this, "Camera Permission denied",Toast.LENGTH_LONG).show();
            }

            @Override
            public void onShowRationale(String[] permissions) {
                //當用戶拒絕某權限時並點擊`再也不提醒`的按鈕時,下次應用再請求該權限時,須要給出合適的響應(好比,給個展現對話框來解釋應用爲何須要該權限)
                Snackbar.make(btn_camera, "須要相機權限去拍照", Snackbar.LENGTH_INDEFINITE)
                        .setAction("ok", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                //必須調用該`setIsPositive(true)`方法
                                helper.setIsPositive(true);
                                helper.request();
                            }
                        }).show();
            }
        })
        //請求權限
        .request();

打完。寫得粗糙。請見諒this

相關文章
相關標籤/搜索