简单粗暴的动态权限虽然看上去步骤也就那么几步,但是如果访问的权限多了。重复写同样的代码也会很麻烦
所以,需要一个助手,那简单化,更加容易操作:利用反射加注解
写一个助手类
PermissionHelper
在这个助手类中,需要传递三个参数
Object Fragment or Activtiy
int 请求码
String... 需要请求的权限
用链式调用 把这些参数添加进来
//链式调用
//Activity
public static PermissionHelper with(Activity activity){
return new PermissionHelper(activity);
}
//Fragment
public static PermissionHelper with(Fragment fragment){
return new PermissionHelper(fragment);
}
//请求码
public PermissionHelper requesCode(int requesCode){
this.mRequesCode = requesCode;
return this;
}
//请求的权限
public PermissionHelper permissions(String... permissions){
this.mRequestPermission = permissions;
return this;
}
不为其他,就是为了感觉高大上
接着就是判断和请求了
PermissionHelper.with(this).requesCode(CLAA_PHONE_REQUEST_CODE)
.permissions(Manifest.permission.CALL_PHONE).request(); //在request()方法中执行
在这个方法中。按照如下步骤
1:判断当前用户的手机是不是6.0版本及以上
创建一个动态申请权限的工具类
PermissionUtils //在这个类中的isOverMarshmallow()方法做判断是不是6.0 及以上
/**
* 判断是不是6.0以上版本
* Marshmallow 棉花糖 6.0 23
* @return
*/
public static boolean isOverMarshmallow(){
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
2:如果不是就直接执行注解标准的方法
@Target(ElementType.METHOD)//放在什么上面 放在方法上面
@Retention(RetentionPolicy.RUNTIME) //什么时候运行
public @interface PermissionSucceed { //成功的注解
public int requestCode();//放一个请求码
}
//也是在PermissionUtils工具类中做处理
public static void executeSuccdMethod(Object object, int requesCode) { //区别申请不懂的权限有一个很重要的东西就是请求码
//执行成功方法
//获取reflectClass 里面的所有方法
Method[] declaredMethods = object.getClass().getDeclaredMethods();
//遍历我们打了标记的方法
for (Method declaredMethod : declaredMethods) {
// Log.e("YacaToy",""+declaredMethod);
//获取这个方法 有没有打这个成功的标记
PermissionSucceed annotation = declaredMethod.getAnnotation(PermissionSucceed.class);
if (annotation != null){
//不等于空的时候 代表打了标记
//并且我们的请求码必须和 mRequesCode 一样
int methodCode = annotation.requestCode();
if (methodCode == requesCode){
//这就是执行的成功方法
//反射执行方法
//找到了该方法
executeMethod(object,declaredMethod);
}
}
}
}
private static void executeMethod(Object object, Method annotation) {
//反射执行方法 第一个是传该方法是属于那个类里面 第二个参数 是传该
try {
annotation.setAccessible(true); //允许执行私有方法
// Log.e("YacaToy","找到了"+annotation);
annotation.invoke(object,new Object[]{});
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
如果不是的6.0版本及以上的话,就不需要申请权限或者判断是否允许权限。就直接反射直接执行代码快
那么如果是6.0 及以上的话,就还要申请权限。基本原理还是和那个简单粗暴的动态申请权限一样的
3:我们需要申请的权限,但是还没有申请过的权限--->拿到这个集合
/**
* 获取没有授予过的的权限
* @param object Activity or Fragmet
* @param requestPermissions
* @return 没有授予过的权限
*/
public static List<String> getDeniedPermissions(Object object, String[] requestPermissions) {
List<String> deniedPermissions = new ArrayList<>();
for (String request : requestPermissions) {
//把没有授予过的权限加入集合当中来
//ContextCompat.checkSelfPermission(getActivity(object),request)== PackageManager.PERMISSION_DENIED //判断是否允许
if (ContextCompat.checkSelfPermission(getActivity(object),request)
== PackageManager.PERMISSION_DENIED){
deniedPermissions.add(request);
}
}
return deniedPermissions;
}
如果全部允许的话,那样就直接执行方法。如果没有允许的就要动态申请权限
//3.3.1 如果授予了 那么我们直接执行方法
if (deniedPermissions.size() == 0){
//全部都是授予过的
//就直接执行
PermissionUtils.executeSuccdMethod(mObject,mRequesCode);
}else {
//3.3.2 如果没有,那么就申请权限
//String[] arr = new String[list.size]; list.toArray(arr);//此时arr就有了list中的值了
//集合转换成数组 (String[])
ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject),
deniedPermissions.toArray(new String[deniedPermissions.size()]),
mRequesCode);
}
同样的要拿到请求的返回值,也就要在onRequestPermissionsResult方法中做处理
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//在动态申请权限的工具类中做处理
PermissionUtils.requestPermissionResult(this, requestCode, permissions);
}
/**
* 处理申请权限的回调
* @param object
* @param requestCode
* @param permissions
*/
public static void requestPermissionResult(
Object object, int requestCode, String[] permissions) {
//再次拿到需到集合返回
List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(object, permissions);
if (deniedPermissions.size() == 0){
//权限用户同意授予了
PermissionUtils.executeSuccdMethod(object,requestCode);
}else{
//如果集合中还是有的元素的话,就说明用户要没有允许。做失败的处理。同样是反射加注解执行方法代码块
//你申请的权限中,有用户不同意的权限
PermissionUtils.executeFailMethod(object,requestCode);
}
}
//执行失败的方法
private static void executeFailMethod(Object object, int requestCode) {
//执行失败方法
//获取object 里面的所有方法
Method[] declaredMethods = object.getClass().getDeclaredMethods();
//遍历我们打了标记的方法
for (Method declaredMethod : declaredMethods) {
// Log.e("YacaToy",""+declaredMethod);
//获取这个方法 有没有打这个成功的标记
//PermissionFail 是失败的注解
PermissionFail annotation = declaredMethod.getAnnotation(PermissionFail.class);
if (annotation != null){
//不等于空的时候 代表打了标记
//并且我们的请求码必须和 mRequesCode 一样
int methodCode = annotation.requestCode();
if (methodCode == requestCode){
//这就是执行的成功方法
//反射执行方法
//找到了该方法
executeMethod(object,declaredMethod);
}
}
}
}
好了:以上就是全部的代码。
如果有不懂的,推荐一篇写的更好的(因为我也是看他写的学到的)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。