AOP在安卓开发中的骚操作(全局双击控制过滤,动态权限获取)

第一次接触到aop大概是16年底的时候,那时候负责对接期货开户sdk,老大想破解其中期货公司展示的名字,问了下同行,说利用aop来实现,当时看了一周完成了业务的开发,也没有过多的思考aop在安卓开发中其他的用处,所以后期不了了之了。近期在坐地铁在掘金上偶然看到一篇介绍安卓中aop使用的文章,又拾起了对aop的兴趣,所以将自己在项目中的一些实践分享给大家

——————————————————————————————————————————————————————————————————————————————————————————————————————————————————

 

先贴下载地址:https://download.csdn.net/download/wcsandlili/11182554

 

1、要想使用aop,必须得引入,目前安卓这一块使用最多的还是AspectJ,看网上各位大佬都说沪江的地址比较稳定,所以我也是引用的,①在项目的classPath添加

classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4'

 

②在app的gradle里面添加引用

implementation ‘org.aspectj:aspectjrt:1.8.13’ 

或者添加插件

apply plugin: 'android-aspectjx'

 

好了,至此aop的引入已经完成,我们可以接下来执行我们的开发了

2、(点击事件拦截处理)要想aop在项目里面能生效,我们首先得创建一个能被aop识别的文件,也就是创建一个class,添加@Aspect的注解

如下

 

我们第一步要创建一个能被aop识别的快速连点过滤的方法,也就是让aop能拦截到我们的点击的方法,这点有点像okhttp的拦截器Interceptor,拦截到我们点击的事件来自动过滤,那么怎么才能拦截?我们通过aop的环绕行@Around来进行安卓原生点击事件的处理,关于aop的一些基本注解和语法建议各位大佬自己在别的博客中查看下,这样理解起来更加的方便,直接给出拦截的方法

@Around("execution(* android.view.View.OnClickListener.onClick(..))") //其实就是拦截安卓原生的点击方法

如果不考虑双击的话用第一个注释的方法,NoDoubleClickUtils就是通过两次点击事件来判断是否过滤掉事件

public class NoDoubleClickUtils {
    private final static int SPACE_TIME = 500;//2次点击的间隔时间,单位ms
    private static long lastClickTime;

    public synchronized static boolean isDoubleClick() {
        long currentTime = System.currentTimeMillis();
        boolean isClick;
        if (currentTime - lastClickTime > SPACE_TIME) {
            isClick = false;
        } else {
            isClick = true;
        }
        lastClickTime = currentTime;
        return isClick;
    }
}

下面的代码是aop中拦截快速连点的处理的方法,其中的 proceedingJoinPoint.proceed();是判断事件能否继续执行下去,如果没有这行代码,相当于我们的事件就此拦截,不能继续执行下去了

 @Around("execution(* android.view.View.OnClickListener.onClick(..))")
    public void onClickLitener(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        if (BuildConfig.DEBUG) {
            LogUtils.e(TAG, "OnClick单击");
        }
        //只考虑单击
//        if (!NoDoubleClickUtils.isDoubleClick()) {
//            proceedingJoinPoint.proceed();
//        }
        //考虑双击控制
        if (isDoubleClick || !NoDoubleClickUtils.isDoubleClick()) {
            proceedingJoinPoint.proceed();
            isDoubleClick = false;
        }
    }

方法拦截日志打印

为了支持特定的界面能执行双击的响应,我们可以通过自定义注解来实现,标记一个全局的变量,通过上面的isDoubleClick来控制判断,代码如下,在需要的地方添加@DoubleClick来实现和拦截

/**
 * 双击自定义注解
 */
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface DoubleClick {

}

使用自定义注解,该点击事件下面全部都能响应双击事件了

 

不添加注解的话默认拦截所有的双击事件(至此项目双击的处理与否已经处理完成)

》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

3、(动态权限拦截处理<配合Rxpermission处理>)

我们拦截动态权限为了获取到声明的权限,所以在自定义注解里面定义一个String[]数组来接受声明的多个权限,注解如下

/**
 * Created by WinWang on 2019/5/15
 * Description->
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestPermissions {
    String[] value();
}

在aop里面通过拦截我们的自定义注解来实现权限的校验,判断继续执行的方法与否

@Around("call(* *..*.*(..)) && @annotation(requestPermissions)")
public void requestPermissions(final ProceedingJoinPoint proceedingJoinPoint, RequestPermissions requestPermissions) throws Exception {
    if (BuildConfig.DEBUG) {
        Log.d(TAG, "----------request permission");
    }
    String[] permissions = requestPermissions.value(); //获取到注解里的权限数组

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        try {
            proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return;
    }
    Object target = proceedingJoinPoint.getTarget();
    FragmentActivity activity = null;
    if (target instanceof Activity) {
        activity = (FragmentActivity) target;
    } else if (target instanceof Fragment) {
        activity = ((Fragment) target).getActivity();
    }

    RxPermissions rxPermissions = new RxPermissions(activity);
    final Activity finalActivity = activity;
    rxPermissions.request(permissions)
            .subscribe(new Consumer<Boolean>() {
                @Override
                public void accept(Boolean granted) throws Exception {
                    if (granted) {
                        try {
                            proceedingJoinPoint.proceed();
                        } catch (Throwable throwable) {
                            throwable.printStackTrace();
                        }
                    } else {
                        Toast.makeText(finalActivity, "未获取到权限,不能继续操作", Toast.LENGTH_LONG).show();
                    }
                }
            });

}

项目中动态权限的使用

就是这么简单,一行代码能实现,不用再去关心每个权限响应的回调了

好了,aop在安卓中的双击过滤以及动态权限的介绍基本也就这么多了,如果想设计更多的操作,希望各位大佬能根据此demo举一反三,运用在自己的项目中,比如全局动态埋点的实现

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值