Android全埋点解决方案-认识

Android全埋点

  • 事件传递机制:onTouchEvent方法返回值

    • true:消费本次事件
    • false:不消费事件,事件向上传递
  • 埋点事件

    • 程序启动
    • 程序退出
    • 页面浏览
    • 点击事件
  • 如何拦截处理逻辑

    • android事件处理机制
  • 如何插入埋点代码逻辑

    • 编译器对代码的处理

      .java->.class->.dex

  • 埋点原理:

    事件拦截,事件前后插入埋点逻辑代码

  • 埋点方式

    • 静态代理:gradle plugin编译期插入代码
    • 动态代理:运行期间的view.onclick回调
  • Android view埋点

    • 可点击控件【button】
    • 可滑动控件【seekbar】
    • 选择控件【checkBox】
  • 绑定listener方式

    • button.setOnClickListener
    • xml文件中android : onclick属性
    • 第三方控件注解绑定 butterknif
  • 0、埋点初始化

    • application中onCreate初始化
    • application记得在xml文件中进行配置
  • 1、页面浏览埋点AppViewScreen

    • activity、fragment切换所执行的生命周期回调
    • activity lifecycle callbacks
      • 该回调需要注册
      • 监听activity生命周期回调
      • 获取当前运行的activity实例
      • 判断activity处于前台还是后台
    • 埋点收集
      • activity名称【包名+类名】
      • 还要加activity的title
    • 完善
      • 每次真正使用之前检查权限
  • 2、App前台、后台埋点

    • 判断方式
      • runningtask
      • runningProcess
      • activitLifecycleCallback【onstart -》onPause】
      • usageStatsManager
      • 无障碍服务
      • /proc目录下的信息
    • android之间进程通讯
      • AIDL【一对多并行】
      • Messager【一对多串行】
      • Bundle【基本数据类型、序列化对象】
      • ContentProvider【Binder机制】
      • BroadcastReceiver
      • 文件共享
      • Socket
    • start事件和end事件触发:可以设置session时间段
    • 缺点
      • 程序崩溃end事件需要在下次启动时候补充
      • 程序卸载,end事件丢失
  • 3、点击事件埋点

    • 关键技术:android.R.id.content setContentView(view)中的view

      • 旧版本就是指ActionBar的下面部分
      • 新版本可能包含ActionBar
    • 原理:

      基于onclickListener的埋点

      • application中onCreate初始化埋点SDK,传入application
      • registerActivitylifecycleCallback注册生命周期回调方法【监控activity生命周期】
      • 拿到当前activity实例,找到对应控件,判断是否设置了可点击属性
      • 代理点击事件,先执行原来的点击事件,再执行埋点事件
      • 缺点:不能采集menuitem点击事件
      • 解决:DecorView引入

      基于Decorview

      • DecorView->LinearLayout->FrameLayout / FrameLayout
      • 获取menuItem:activity.getWindow().getDecorView()
      • 缺点:无法采集onResume生命周期之后创建view的点击事件
      • 解决:viewTreeObserver.OnGlobalLayoutListener引用

      基于viewTreeObserver.OnGlobalLayoutListener

      • 视图树发生变化将会被监听到,onGlobalLayout被回调,此时重新遍历代理点击事件【上述提到】
      • 建议:页面退出时候remove onGlobalLayout的监听事件
    • 缺点:反射、动态代理的效率低

      基于window.Callback

      • 拿到activity实例
      • 拿到window.callback对象【自定义代理该对象】
      • 在该方法里面的事件分发方法dispatchTouchEvent插入埋点
      • 通过dispatchTouchEvent的参数MotionEvent查找到被点击的view对象【处理事件类型:按下,抬起】
      • 缺点:
        • 每次点击都需要遍历RootView
        • API15+支持
        • ActivityLifecycleCallbacks API14+支持
        • 无法采集游离在activity之外的控件【dialog、popupwindow】

      基于View.AccessobilityDelegate】 辅助工具,视觉、听觉障碍

      • view被点击
      • 先调用原有的点击监听事件
      • 再调用accessbilityDelegate
      • **缺点:**需要手动开启 设置->辅助功能
  • 4、触摸事件埋点

    • 透明层
      • 每个activity最上面一层有一个覆盖一个透明的view【实现一个方法传入activity,为其添加透明层】
      • 点击事件发生都会先被接受
      • 重写onTouchEvent,在调用super之前判断坐标信息
      • 在rootview中查找实际被点击的view对象
      • 在原有的onclick中处理逻辑,插入埋点代码
  • 5、Aspectj埋点【AOP】

    • 问题:埋点对代码的侵入性,需要使用非侵入性
    • 解决:Aspectj AOP工具
    • 原理:在class文件生成后,dex文件生成前,找到符合aspectj的切点,然后织入埋点代码【编译期间插入代码到目标程序-》关键是ajc编译器】
    • aspectj实现步骤
      • 织入点@Pointcut(指定织入的方法)
        • call 调入点:织入代码出现在方法前后
        • execute 执行点:织入代码出现在方法中
      • 织入代码@Before、@After、@Around【埋点代码】
      • 面向切面的配置文件【类】@Aspect
      • 需要编译生成plugin插件配合使用
    • 缺点: 无法采集到的点击事件
      • butterknife @onClick绑定的事件
      • android:onclick绑定的事件
      • menuitem事件
      • onclickListenner中使用了lambda语法的事件
  • 6、ASM【字节码操作和分析框架】

    • 原理:.class文件转换成.dex文件之前进行一个埋点代码的插入【通过在class文件中找到插入位置】
      • 字节码插桩
      • 代码注入
      • 自定义gradle plugin
  • 7、Javassist

    • ClassPool
  • 8、AST

    • 注解处理器【Javac的工具】
    • Element对象【Element数组】
  • 9、 其他

    • 动态代理技术
      • Java Proxy
      • ASM
      • AspectJ
      • javassist

总结:最终实现还是在.calss文件和.dex文件之间进行代码的注入更为理想。

有Java Proxy动态代理技术为起点接下来深入学习各种动态技术【即.class -> .dex 之间进行代码插入技术】

你可能感兴趣的:(Android)