Android运行时权限处理

327 阅读4分钟

使用方式

通过 PermissionUtil 对象作为门面将库暴露给使用模块。主要设置了 AppCompatActivity 和 Fragment 中获取权限的途径。

public class PermissionUtil {

    public static PermissionWrapper with(AppCompatActivity activity) {
        return new PermissionWrapper(activity);
    }
    
    public static PermissionWrapper with(Fragment fragment) {
        return new PermissionWrapper(fragment);
    }
}

将有关权限的操作封装成了 PermissionWrapper 对象。主要包括了判断权限是否获取,请求单个权限和请求多个权限的功能。

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 进行比较返回结果。

调用方式:

boolean hasContactsPermission = PermissionUtil.with(this).isGranted(Manifest.permission.WRITE_CONTACTS);
  • 请求单个权限和请求多个权限的功能

因为涉及到请求权限,我们将需要请求的权限封装成 PermissionRequestWrapper。

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() 方法发起,通过传入的请求码进行标示。

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 保存在一个集合中。因为有可能我们会重复请求权限,所以需要判断哪些权限已经请求。

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 ,判断是否进行权限请求。

  • 请求多个权限

与请求单个权限同样。只是将单个权限封装为一个集合进行处理。

方法回调

通过返回的 PermissionRequestWrapper 方法,可以设置对应的回调方法。包括合理的,同意的,拒绝的,获取所有参数的方法。

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);
}