AspectJ切面实现Android权限请求框架

实现思路:搭配AspectJ切面思想,对需要请求权限的方法进行拦截修改(Around语法),Around语法的作用主要是用来修改需要切入的方法以及方法的参数,参照这一便利,我们在定义的切面方法中新启动一个透明主题的activity作一个权限请求的统一处理的界面,搭配

EasyPermissions权限请求框架,这里作为方便,其实完全可以应业务要求自己封装,

我们可以在将请求权限的结果作为方法的参数进行返回。具体代码思路如下:

//权限请求方法注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface PermissionCheck {
    String[] value() default {};

    int requestCode();
}

 

//封装权限请求code 返回结果的bean类

public class PermissionsResult {
    int requestCode;
    int resultCode;
    List<String> permissions;
    List<String> successPermissions;
    List<String> failurePermissions;

    public List<String> getSuccessPermissions() {
        return successPermissions;
    }

    public List<String> getFailurePermissions() {
        return failurePermissions;
    }

    public int getRequestCode() {
        return requestCode;
    }

    public int getResultCode() {
        return resultCode;
    }

    public List<String> getPermissions() {
        return permissions;
    }

    public PermissionsResult(Builder builder) {
        this.requestCode = builder.requestCode;
        this.resultCode = builder.resultCode;
        this.permissions = builder.permissions;
        this.successPermissions = builder.successPermissions;
        this.failurePermissions = builder.failurePermissions;
    }


    public static class Builder{
        int requestCode;
        int resultCode;
        List<String> permissions;
        List<String> successPermissions;
        List<String> failurePermissions;
        public Builder() {
        }

        public Builder setRequestCode(int requestCode) {
            this.requestCode = requestCode;
            return this;
        }

        public Builder setResultCode(int resultCode) {
            this.resultCode = resultCode;
            return this;
        }

        public Builder setPermissions(List<String> permissions) {
            this.permissions = permissions;
            return this;
        }

        public Builder setSuccessPermissions(List<String> successPermissions) {
            this.successPermissions = successPermissions;
            return this;
        }

        public Builder setFailurePermissions(List<String> failurePermissions) {
            this.failurePermissions = failurePermissions;
            return this;
        }

        public PermissionsResult build(){
            return new PermissionsResult(this);
        }
    }


}

//AspectJ类中定义的切面方法

@Around("call(* *(xx.xx.xx.PermissionsResult)) && @annotation(permissionCheck)")
    public Object check(final ProceedingJoinPoint point, PermissionCheck permissionCheck){
        Log.e("---", "进入切面");
        Object target = point.getTarget();
        if(null == target) return null;
        Context context = null;
        if (target instanceof Activity) {
            context = (Context) target;
        } else if (target instanceof Fragment) {
            context = ((Fragment) target).getActivity();
        }else if(target instanceof BaseViewModel){
            context = ((BaseViewModel) target).getApplication();
        }else if(target instanceof SystemHeadCallBack){
//            context = ((SystemHeadCallBack) target).getmContext();
        }else if(target instanceof Service){
            context = ((Service) target).getApplicationContext();
        }

        String[] permissions = permissionCheck.value();
        Object[] objects = new Object[1];
        if (context != null) {
            //做权限是否有的判断
            if (EasyPermissions.hasPermissions(context, permissions)) {
                try {
                    objects[0] = point.proceed(new Object[]{new PermissionsResult.Builder()
                            .setResultCode(1)
                            .setSuccessPermissions(Arrays.asList(permissionCheck.value())).build()});
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
            } else {
                int requestCode = permissionCheck.requestCode();
                PermissionCheckActivity.startPermissionCheckActivity(
                        context, permissions, requestCode , new PermissionBack() {
                            @Override
                            public void permissionsCallBack(PermissionsResult permissionsResult) {
                                int returnRequestCode = permissionsResult.getRequestCode();
                                if(requestCode == returnRequestCode){ //校验
                                    try {
                                        objects[0] = point.proceed(new Object[]{permissionsResult});
                                    } catch (Throwable throwable) {
                                        throwable.printStackTrace();
                                    }
                                }
                            }
                        }
                );

            }

        }
        return objects[0];
    }

//透明主题的activity

public class PermissionCheckActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {

    public static PermissionBack permissionBack;
    int requestCode;

    public static void startPermissionCheckActivity(Context context, String[] permissions,
                                                    int requestCode,
                                                    PermissionBack back){
        Intent intent = new Intent(context, PermissionCheckActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        Bundle bundle = new Bundle();
        bundle.putStringArray("permissions", permissions);
        bundle.putInt("requestCode", requestCode);
        intent.putExtras(bundle);
        permissionBack = back;
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_FULLSCREEN);
        StatusBarCompat.translucentStatusBar(this, true, false, getResources().getColor(R.color.transparent_00000000));
        super.onCreate(savedInstanceState);
        Intent intent = getIntent();
        Bundle extras = intent.getExtras();
        if (null == extras) return;
        requestCode = Objects.requireNonNull(extras).getInt("requestCode");
        String[] permissions = extras.getStringArray("permissions");
        if (permissions == null || permissions.length <= 0) {
            finish();
        } else {
            //首次会直接请求权限,如果之前权限请求拒绝过 那么就弹提示开启权限的框 确定之后再去请求权限
            EasyPermissions.requestPermissions(this, getString(R.string.post_message_albums_permission), requestCode, permissions);

        }
    }

    /**
     *
     */
    @Override
    public void onPermissionsGranted(int requestCode, List<String> perms) {

    }

    /**
     * dialog的取消按钮也会回调这个方法
     */
    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
        finish();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
        if(grantResults.length <= 0){
            return;
        }
        boolean isSuccess  = true;
        List<String> perms = new ArrayList<>();
        List<String> successPermissions = new ArrayList<>();
        List<String> failurePermissions = new ArrayList<>();
        for (int i = 0;i < grantResults.length;i++){
            if(grantResults[i] == -1){ // -1表示该权限是被拒绝了的
                Log.e("--onRequestPermission", permissions[i] + "授权失败");
                failurePermissions.add(permissions[i]);
                isSuccess = false;
            }else {
                successPermissions.add(permissions[i]);
                Log.e("--onRequestPermission", permissions[i] + "授权成功");
            }
            perms.add(permissions[i]);
        }
        permissionBack.permissionsCallBack(new PermissionsResult.Builder()
                .setRequestCode(requestCode)
                .setPermissions(perms)
                .setSuccessPermissions(successPermissions)
                .setFailurePermissions(failurePermissions)
                .setResultCode(isSuccess ? 1 : 0).build());
        finish();
    }

在透明Activity中将权限请求结果进行回调到切面方法中,调用

point.proceed(new Object[]{permissionsResult});将权限请求结果的值作为参数传入到proceed方法.

具体使用:
 

@PermissionCheck(value = {
        Manifest.permission.ACCESS_FINE_LOCATION}, requestCode = 10000)
public Object check(PermissionsResult result){
    if(null == result){
        return "1";
    }
    int resultCode = result.getResultCode();
    // TODO: 2019/11/14 根据返回的值来确定做什么逻辑
    Log.e("--check权限返回code", resultCode + "");
    return "2";
}

在需要作权限请求的位置 直接调用 check(null);参数可以随意传,因为编译代码时AspectJ会重新对该方法进行改造。具体原理涉及到字节码改造了,不作详细说明,因为我也了解不深 哈哈哈哈。

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值