Android運行時權限處理

使用方式

經過 PermissionUtil 對象做爲門面將庫暴露給使用模塊。主要設置了 AppCompatActivity 和 Fragment 中獲取權限的途徑。bash

public class PermissionUtil {

    public static PermissionWrapper with(AppCompatActivity activity) {
        return new PermissionWrapper(activity);
    }
    
    public static PermissionWrapper with(Fragment fragment) {
        return new PermissionWrapper(fragment);
    }
}
複製代碼

將有關權限的操做封裝成了 PermissionWrapper 對象。主要包括了判斷權限是否獲取,請求單個權限和請求多個權限的功能。app

public static class PermissionWrapper {
    private AppCompatActivity mActivity;
    private Fragment mFragment;

    PermissionWrapper(AppCompatActivity activity) {
        mActivity = activity;
    }

    PermissionWrapper(Fragment fragment) {
        mFragment = fragment;
    }

    public boolean isGranted(String permissionType) {
        int permissionCheck;
        if (mActivity != null) {
            permissionCheck = ContextCompat.checkSelfPermission(mActivity, permissionType);
        } else {
            permissionCheck = ContextCompat.checkSelfPermission(mFragment.getContext(), permissionType);
        }
        return permissionCheck == PackageManager.PERMISSION_GRANTED;
    }

    public PermissionRequestWrapper request(String permissionType) {
        if (mActivity != null) {
            return new PermissionRequestWrapper(mActivity, new String[]{permissionType});
        } else {
            return new PermissionRequestWrapper(mFragment, new String[]{permissionType});
        }
    }

    public PermissionRequestWrapper request(String ... permissionTypes) {
        if (mActivity != null) {
            return new PermissionRequestWrapper(mActivity, permissionTypes);
        } else {
            return new PermissionRequestWrapper(mFragment, permissionTypes);
        }
    }
}
複製代碼
  • 判斷權限是否獲取

直接調用系統方法 ContextCompat.checkSelfPermission(),經過返回值與 PackageManager.PERMISSION_GRANTED 進行比較返回結果。ide

調用方式:ui

boolean hasContactsPermission = PermissionUtil.with(this).isGranted(Manifest.permission.WRITE_CONTACTS);
複製代碼
  • 請求單個權限和請求多個權限的功能

由於涉及到請求權限,咱們將須要請求的權限封裝成 PermissionRequestWrapper。this

public static class PermissionRequestWrapper {
    private static final String TAG = PermissionRequestWrapper.class.getSimpleName();
    private AppCompatActivity mActivity;
    private Fragment mFragment;
    private Func mDenyFunc;
    private Func mGrantFunc;
    private String[] mPermissionTypes;
    private List<SinglePermission> mPermissionsWeDontHave;
    private Func3 mRationalFunc;
    private int mRequestCode;
    private Func2 mResultFunc;

    public PermissionRequestWrapper(AppCompatActivity activity, String[] permissionTypes) {
        mActivity = activity;
        mPermissionTypes = permissionTypes;
    }

    public PermissionRequestWrapper(Fragment fragment, String[] permissionTypes) {
        mFragment = fragment;
        mPermissionTypes = permissionTypes;
    }

    public PermissionRequestWrapper requestCode(int reqCode) {
        mRequestCode = reqCode;
        int length = mPermissionTypes.length;
        mPermissionsWeDontHave = new ArrayList<>(length);
        for (String permissionType : mPermissionTypes) {
            mPermissionsWeDontHave.add(new SinglePermission(permissionType));
        }

        if (needToRequest()) {
            Log.i(TAG, "Asking for permission");
            if (mActivity != null) {
                ActivityCompat.requestPermissions(mActivity, mPermissionTypes, reqCode);
            } else {
                mFragment.requestPermissions(mPermissionTypes, reqCode);
            }
        } else {
            Log.i(TAG, "No need to ask for permission");
            if (mGrantFunc != null) {
                mGrantFunc.call();
            }
        }
        return this;
    }

    private boolean needToRequest() {
        List<SinglePermission> neededPermissions = new ArrayList<>(mPermissionsWeDontHave);
        for (int i = 0; i < mPermissionsWeDontHave.size(); i++) {
            SinglePermission perm = mPermissionsWeDontHave.get(i);
            int checkRes;
            if (mActivity != null) {
                checkRes = ContextCompat.checkSelfPermission(mActivity, perm.getPermissionName());
            } else {
                checkRes = ContextCompat.checkSelfPermission(mFragment.getContext(), perm.getPermissionName());
            }
            if (checkRes == PackageManager.PERMISSION_GRANTED) {
                neededPermissions.remove(perm);
            } else {
                boolean shouldShowRequestPermissionRationale;
                if (mActivity != null) {
                    shouldShowRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(mActivity, perm.getPermissionName());
                } else {
                    shouldShowRequestPermissionRationale = mFragment.shouldShowRequestPermissionRationale(perm.getPermissionName());
                }
                if (shouldShowRequestPermissionRationale) {
                    perm.setRationalNeeded(true);
                }
            }
        }
        mPermissionsWeDontHave = neededPermissions;
        mPermissionTypes = new String[mPermissionsWeDontHave.size()];
        for (int i = 0; i < mPermissionsWeDontHave.size(); i++) {
            mPermissionTypes[i] = mPermissionsWeDontHave.get(i).getPermissionName();
        }
        return mPermissionsWeDontHave.size() != 0;
    }

    public PermissionRequestWrapper onRational(Func3 rationalFunc) {
        mRationalFunc = rationalFunc;
        return this;
    }

    public PermissionRequestWrapper onAllGranted(Func grantFunc) {
        mGrantFunc = grantFunc;
        return this;
    }

    public PermissionRequestWrapper onAnyDenied(Func denyFunc) {
        mDenyFunc = denyFunc;
        return this;
    }

    public PermissionRequestWrapper onResult(Func2 resultFunc) {
        mResultFunc = resultFunc;
        return this;
    }

    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        if (mRequestCode == requestCode) {
            if (mResultFunc != null) {
                Log.i(TAG, "Calling Results Func");
                mResultFunc.call(requestCode, permissions, grantResults);
                return;
            }

            for (int i = 0; i < permissions.length; i++) {
                if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
                    if (mPermissionsWeDontHave.get(i).isRationalNeeded() && mRationalFunc != null) {
                        Log.i(TAG, "Calling Rational Func");
                        mRationalFunc.call(mPermissionsWeDontHave.get(i).getPermissionName());
                    } else if (mDenyFunc != null) {
                        Log.i(TAG, "Calling Deny Func");
                        mDenyFunc.call();
                    } else {
                        Log.e(TAG, "NUll DENY FUNCTIONS");
                    }

                    return;
                }
            }

            if (mGrantFunc != null) {
                Log.i(TAG, "Calling Grant Func");
                mGrantFunc.call();
            } else {
                Log.e(TAG, "NUll GRANT FUNCTIONS");
            }
        }
    }
}
複製代碼
  • 請求單個權限

請求權限是經過 PermissionRequestWrapper.requestCode() 方法發起,經過傳入的請求碼進行標示。spa

public PermissionRequestWrapper requestCode(int reqCode) {
    mRequestCode = reqCode;
    int length = mPermissionTypes.length;
    mPermissionsWeDontHave = new ArrayList<>(length);
    for (String permissionType : mPermissionTypes) {
        mPermissionsWeDontHave.add(new SinglePermission(permissionType));
    }

    if (needToRequest()) {
        Log.i(TAG, "Asking for permission");
        if (mActivity != null) {
            ActivityCompat.requestPermissions(mActivity, mPermissionTypes, reqCode);
        } else {
            mFragment.requestPermissions(mPermissionTypes, reqCode);
        }
    } else {
        Log.i(TAG, "No need to ask for permission");
        if (mGrantFunc != null) {
            mGrantFunc.call();
        }
    }
    return this;
}
複製代碼

mPermissionTypes 是經過構建 PermissionRequestWrapper 對象時傳入的,表明了想要請求的全部權限。並將它封裝爲請求對象 SinglePermission 保存在一個集合中。由於有可能咱們會重複請求權限,因此須要判斷哪些權限已經請求。code

private boolean needToRequest() {
    List<SinglePermission> neededPermissions = new ArrayList<>(mPermissionsWeDontHave);
    for (int i = 0; i < mPermissionsWeDontHave.size(); i++) {
        SinglePermission perm = mPermissionsWeDontHave.get(i);
        int checkRes;
        if (mActivity != null) {
            checkRes = ContextCompat.checkSelfPermission(mActivity, perm.getPermissionName());
        } else {
            checkRes = ContextCompat.checkSelfPermission(mFragment.getContext(), perm.getPermissionName());
        }
        if (checkRes == PackageManager.PERMISSION_GRANTED) {
            neededPermissions.remove(perm);
        } else {
            boolean shouldShowRequestPermissionRationale;
            if (mActivity != null) {
                shouldShowRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(mActivity, perm.getPermissionName());
            } else {
                shouldShowRequestPermissionRationale = mFragment.shouldShowRequestPermissionRationale(perm.getPermissionName());
            }
            if (shouldShowRequestPermissionRationale) {
                perm.setRationalNeeded(true);
            }
        }
    }
    mPermissionsWeDontHave = neededPermissions;
    mPermissionTypes = new String[mPermissionsWeDontHave.size()];
    for (int i = 0; i < mPermissionsWeDontHave.size(); i++) {
        mPermissionTypes[i] = mPermissionsWeDontHave.get(i).getPermissionName();
    }
    return mPermissionsWeDontHave.size() != 0;
}
複製代碼

在方法中會遍歷全部請求的權限,而後經過系統方法 ContextCompat.checkSelfPermission() 判斷是否獲取過。獲取過則從集合中移除,沒有獲取過則跳過。最後經過集合中的權限請求數是否爲 0 ,判斷是否進行權限請求。對象

  • 請求多個權限

與請求單個權限一樣。只是將單個權限封裝爲一個集合進行處理。rem

方法回調

經過返回的 PermissionRequestWrapper 方法,能夠設置對應的回調方法。包括合理的,贊成的,拒絕的,獲取全部參數的方法。get

public PermissionRequestWrapper onRational(Func3 rationalFunc) {
    mRationalFunc = rationalFunc;
    return this;
}

public PermissionRequestWrapper onAllGranted(Func grantFunc) {
    mGrantFunc = grantFunc;
    return this;
}

public PermissionRequestWrapper onAnyDenied(Func denyFunc) {
    mDenyFunc = denyFunc;
    return this;
}

public PermissionRequestWrapper onResult(Func2 resultFunc) {
    mResultFunc = resultFunc;
    return this;
}

public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    if (mRequestCode == requestCode) {
        if (mResultFunc != null) {
            Log.i(TAG, "Calling Results Func");
            mResultFunc.call(requestCode, permissions, grantResults);
            return;
        }

        for (int i = 0; i < permissions.length; i++) {
            if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
                if (mPermissionsWeDontHave.get(i).isRationalNeeded() && mRationalFunc != null) {
                    Log.i(TAG, "Calling Rational Func");
                    mRationalFunc.call(mPermissionsWeDontHave.get(i).getPermissionName());
                } else if (mDenyFunc != null) {
                    Log.i(TAG, "Calling Deny Func");
                    mDenyFunc.call();
                } else {
                    Log.e(TAG, "NUll DENY FUNCTIONS");
                }

                return;
            }
        }

        if (mGrantFunc != null) {
            Log.i(TAG, "Calling Grant Func");
            mGrantFunc.call();
        } else {
            Log.e(TAG, "NUll GRANT FUNCTIONS");
        }
    }
}
複製代碼

而後在 Activity 和 Fragment 的 onRequestPermissionsResult() 方法中進行調用 PermissionRequestWrapper 的 onRequestPermissionsResult() 方法。

@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
複製代碼
相關文章
相關標籤/搜索