Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in D:\site\54cainiao\web\config\function.php on line 295 Android埋点方案的简单实现-AOP之AspectJ - 54菜鸟
11

Android埋点方案的简单实现-AOP之AspectJ

  • 时间:2020-01-28 13:40 编辑:54菜鸟 来源: 阅读:541
  • 扫一扫,手机访问
摘要:AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。

AOP的定义

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。


以上关于AOP的定义引用自百度百科。


AOP的运用场景

日志记录、性能统计、权限控制、埋点等


AOP的具体实现方案有很多,这里选用AspectJ来简单实现


监听View的点击、页面打开、关闭

为方法添加开始、结束的日志

统计方法运行时间

AspectJ的使用

AspectJ的引入

这里引用AspectJX,AspectJX是基于AspectJ的一个AOP框架


新建Android工程,在项目根目录下的build.gradle文件中添加依赖


dependencies {

        //...

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

        //...

    }

新建Module,类型选择Android Library,在新建的library的build.gradle文件中,添加相应的依赖


apply plugin: 'android-aspectjx'

在app的build.gradle文件中增加对刚才新建的library的引用及AspectJ的依赖


apply plugin: 'android-aspectjx'


dependencies {

    //...

    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'

}

监听View的点击、页面打开、关闭

在library中新建回调接口TrackCallBack


public interface TrackCallBack {


    /**

     * 当View被点击

     *

     * @param pageName

     * @param viewIdName

     */

    void onClick(String pageName, String viewIdName);


    /**

     * 当页面打开时

     *

     * @param pageName

     */

    void onPageOpen(String pageName);


    /**

     * 当页面关闭时

     *

     * @param pageName

     */

    void onPageClose(String pageName);


}

在library中新建切入点TrackPoint


public class TrackPoint {


    private static TrackCallBack mTrackCallBack;


    private TrackPoint() {


    }


    /**

     * 初始化

     * @param trackCallBack

     */

    public static void init(TrackCallBack trackCallBack) {

        mTrackCallBack = trackCallBack;

    }


    static void onClick(String pageName, String viewIdName) {

        if (mTrackCallBack == null) {

            return;

        }

        mTrackCallBack.onClick(pageName, viewIdName);

    }


    static void onPageOpen(String pageName) {

        if (mTrackCallBack == null) {

            return;

        }

        mTrackCallBack.onPageOpen(pageName);

    }


    static void onPageClose(String pageName) {

        if (mTrackCallBack == null) {

            return;

        }

        mTrackCallBack.onPageClose(pageName);

    }


}

在library中新建切面TraceAspect


@Aspect

public class TraceAspect {


    private static final String TAG = TraceAspect.class.getSimpleName();


    @Pointcut("execution(* onClick(..))")

    public void onClickPointcut() {


    }


    @Pointcut("execution(* android.app.Activity+.onCreate(..))")

    public void activityOnCreatePointcut() {


    }


    @Pointcut("execution(* android.app.Activity+.onDestroy(..))")

    public void activityDestroyPointcut() {


    }


    @Around("onClickPointcut()")

    public void onClick(ProceedingJoinPoint joinPoint) throws Throwable {

        Object target = joinPoint.getTarget();

        String className = "";

        if (target != null) {

            className = target.getClass().getName();

        }

        Object[] args = joinPoint.getArgs();

        if (args.length > 0 && args[0] instanceof View) {

            View view = (View) args[0];

            String entryName = view.getResources().getResourceEntryName(view.getId());

            TrackPoint.onClick(className, entryName);

        }

        joinPoint.proceed();

    }


    @Around("activityOnCreatePointcut()")

    public void pageOpen(ProceedingJoinPoint joinPoint) throws Throwable {

        Object target = joinPoint.getTarget();

        String className = target.getClass().getName();

        TrackPoint.onPageOpen(className);

        joinPoint.proceed();

    }


    @Around("activityDestroyPointcut()")

    public void pageClose(ProceedingJoinPoint joinPoint) throws Throwable {

        Object target = joinPoint.getTarget();

        String className = target.getClass().getName();

        TrackPoint.onPageClose(className);

        joinPoint.proceed();

    }


}

在app模块新建Application,在onCreate中执行初始化:


public class App extends Application {


    private static final String TAG = TraceAspect.class.getSimpleName();


    @Override

    public void onCreate() {

        super.onCreate();

        TrackPoint.init(new TrackCallBack() {

            @Override

            public void onClick(String pageName, String viewIdName) {

                Log.d(TAG, "onClick:" + pageName + "-" + viewIdName);

                //执行相应的业务

            }


            @Override

            public void onPageOpen(String pageName) {

                Log.d(TAG, "onPageOpen:" + pageName);

                //执行相应的业务

            }


            @Override

            public void onPageClose(String pageName) {

                Log.d(TAG, "onPageClose:" + pageName);

                //执行相应的业务

            }

        });

    }

}

新增的Application需要在AndroidManifest中引用才会生效。


运行App后,点击打开另一个Activity,然后依次退出Activity,输出日志如下:


2020-01-13 16:50:17.373 16610-16610/com.wangyz.aspectjdemo D/TraceAspect: onPageOpen:com.wangyz.aspectjdemo.MainActivity

2020-01-13 16:50:19.243 16610-16610/com.wangyz.aspectjdemo D/TraceAspect: onClick:com.wangyz.aspectjdemo.MainActivity-btn_open

2020-01-13 16:50:19.298 16610-16610/com.wangyz.aspectjdemo D/TraceAspect: onPageOpen:com.wangyz.aspectjdemo.SecondActivity

2020-01-13 16:50:21.392 16610-16610/com.wangyz.aspectjdemo D/TraceAspect: onPageClose:com.wangyz.aspectjdemo.SecondActivity

2020-01-13 16:50:22.320 16610-16610/com.wangyz.aspectjdemo D/TraceAspect: onPageClose:com.wangyz.aspectjdemo.MainActivity

为方法添加开始、结束的日志

在library中增加注解AddLog


@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface AddLog {

}

在TraceAspect增加以下代码


@Pointcut("execution(@com.wangyz.library.AddLog * *(..))")

    public void addLogPointcut() {


    }


@Around("addLogPointcut()")

    public void addLog(ProceedingJoinPoint joinPoint) throws Throwable {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        AddLog addLog = signature.getMethod().getAnnotation(AddLog.class);

        if (addLog != null) {

            Object target = joinPoint.getTarget();

            String className = "";

            if (target != null) {

                className = target.getClass().getName();

            }

            Log.d(TAG, "start execute:" + className + "-" + signature.getMethod().getName());

            joinPoint.proceed();

            Log.d(TAG, "end execute:" + className + "-" + signature.getMethod().getName());

        } else {

            joinPoint.proceed();

        }

    }

在MainActivity的onCreate上增加AddLog注解


@AddLog

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        //...

    }

运行App后,输入日志如下:


2020-01-13 16:50:17.373 16610-16610/com.wangyz.aspectjdemo D/TraceAspect: start execute:com.wangyz.aspectjdemo.MainActivity-onCreate

2020-01-13 16:50:17.392 16610-16610/com.wangyz.aspectjdemo D/TraceAspect: end execute:com.wangyz.aspectjdemo.MainActivity-onCreate

统计方法运行时间

在library中增加注解ExecTime


@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface ExecTime {

}

在TraceAspect增加以下代码


@Pointcut("execution(@com.wangyz.library.ExecTime * *(..))")

    public void execTimePointcut() {


    }


@Around("execTimePointcut()")

    public void execTime(ProceedingJoinPoint joinPoint) throws Throwable {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        ExecTime execTime = signature.getMethod().getAnnotation(ExecTime.class);

        if (execTime != null) {

            long start = System.currentTimeMillis();

            joinPoint.proceed();

            long end = System.currentTimeMillis();

            Object target = joinPoint.getTarget();

            String className = "";

            if (target != null) {

                className = target.getClass().getName();

            }

            Log.d(TAG,

                    "execute time:" + className + "-" + signature.getMethod().getName() + " : " + (end - start) + "ms");

        } else {

            joinPoint.proceed();

        }

    }

在onClick方法上增加ExecTime注解


@ExecTime

    @Override

    public void onClick(View v) {

        switch (v.getId()) {

            case R.id.btn_open:

                Intent intent = new Intent(this, SecondActivity.class);

                startActivity(intent);

                break;

            default:

                break;

        }

    }

运行App后,输出日志如下:

2020-01-13 16:50:19.272 16610-16610/com.wangyz.aspectjdemo D/TraceAspect: execute time:com.wangyz.aspectjdemo.MainActivity-onClick : 28ms

源码地址:https://github.com/milovetingting/Samples/tree/master/AspectJDemo


  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【织梦cms|织梦技巧】织梦默认作者和默认泉源修改(2021-12-08 10:11)
【织梦cms|织梦技巧】 织梦dedecms差异栏目导航显示差异样式的方式(2021-12-08 10:09)
【织梦cms|织梦技巧】织梦dede新建模型中自定义联动类别调用(2020-03-01 13:52)
【织梦cms|织梦技巧】织梦CMS标签中出现“系统无此标签,可能已经移除”(2020-03-01 13:51)
【织梦cms|织梦技巧】dedecms织梦系统后台验证码图片不显示的解决方法(2020-03-01 13:51)
【织梦cms|织梦技巧】dedecms更新文章会出现空白页(2020-03-01 13:50)
【织梦cms|织梦技巧】让织梦dedecms搜索结果按照点击数排序(2020-03-01 13:48)
【织梦cms|织梦技巧】在dedecms织梦内容页中调用文章缩略图(2020-03-01 13:47)
【织梦cms|织梦技巧】在dedecms织梦添加自制的背景图片(2020-03-01 13:47)
【织梦cms|织梦技巧】修改织梦dedecms幻灯片属性(2020-03-01 13:46)