Android全埋点解决方案-认识
16lz
2022-05-03
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插件配合使用
- 织入点@Pointcut(指定织入的方法)
- 缺点: 无法采集到的点击事件
- butterknife @onClick绑定的事件
- android:onclick绑定的事件
- menuitem事件
- onclickListenner中使用了lambda语法的事件
-
6、ASM【字节码操作和分析框架】
- 原理:.class文件转换成.dex文件之前进行一个埋点代码的插入【通过在class文件中找到插入位置】
- 字节码插桩
- 代码注入
- 自定义gradle plugin
- 原理:.class文件转换成.dex文件之前进行一个埋点代码的插入【通过在class文件中找到插入位置】
-
7、Javassist
- ClassPool
-
8、AST
- 注解处理器【Javac的工具】
- Element对象【Element数组】
-
9、 其他
- 动态代理技术
- Java Proxy
- ASM
- AspectJ
- javassist
- 动态代理技术
总结:最终实现还是在.calss文件和.dex文件之间进行代码的注入更为理想。
有Java Proxy动态代理技术为起点接下来深入学习各种动态技术【即.class -> .dex 之间进行代码插入技术】
更多相关文章
- Android(安卓)文件操作详解及简单实例
- Android(安卓)APIDemos 研读之一:android.graphics.Movie
- Android小項目之ListView实现论坛管理效果
- Android(安卓)monkey介绍
- Android中单击空白区域隐藏键盘
- 【Android】实现全屏、无标题栏效果
- Android简明开发教程十九:线程 Bezier曲线
- 在Android上用PHP编写应用- PFA初探
- 【Android】ViewPager实现图片左右滑动播放及添加点击事件