原文出自:http://www.lxweimin.com/p/dd253314ba6b
下面說得內(nèi)容會涉及幾個關(guān)鍵詞:AOP、AspectJ、Gradle、plugin、ASM
基于用戶行為數(shù)據(jù)的重要性,我在公司內(nèi)部推動了一項全埋點數(shù)據(jù)收集的專項項目。主要的解決方案來自《Android全埋點解決方案》這本書,現(xiàn)學(xué)現(xiàn)用。
一、Activity生命周期狀態(tài)監(jiān)控
通過Application的registerActivityLifecycleCallbacks方法,監(jiān)聽所有Activity的生命周期回調(diào)。書中的例子只監(jiān)聽onActivityResumed回調(diào),因為onResumed方法必定會執(zhí)行。
源碼:https://github.com/wangzhzh/AutoTrackAppViewScreen
二、AppStart、AppEnd事件監(jiān)控
記錄AppStart事件:依然是通過Application的registerActivityLifecycleCallbacks方法,監(jiān)聽onActivityStarted回調(diào),記錄AppStart事件。
記錄AppEnd事件:內(nèi)部實現(xiàn)一個CountDownTimer計數(shù)器,如果Activity執(zhí)行了onActivityPaused回調(diào),則計數(shù)器開始工作,倒計時30秒后則是做AppEnd。
這里有一個問題需要處理,由于Android是一個多進(jìn)程的實現(xiàn)邏輯,如果一個程序有多進(jìn)程的實現(xiàn)邏輯,如果另一個進(jìn)程依然在工作,則不能執(zhí)行AppEnd的事件統(tǒng)計。一個進(jìn)程怎么知道另一個進(jìn)程是否在執(zhí)行任務(wù)?可以用ContentProvider+SQLite+ContentObserver。
源碼:https://github.com/wangzhzh/AutoTrackAppStartAppEnd
三、AppClick事件監(jiān)控
控件的點擊事件記錄是最麻煩的,實現(xiàn)方案有好幾種。
1、代理ClickListener方式
源碼:https://github.com/wangzhzh/AutoTrackAppClick1
2、代理Window.Callback
源碼:https://github.com/wangzhzh/AutoTrackAppClick2
3、4、代理View.AccessibilityDelegate、 透明層
源碼:https://github.com/wangzhzh/AutoTrackAppClick3
源碼:https://github.com/wangzhzh/AutoTrackAppClick4
以上方式或多或少都有各自的問題,要么用了反射,影響性能,要么用了新api的方法,對舊系統(tǒng)不兼容。強(qiáng)伯癥的人會糾結(jié)的要死。
5、AspectJ
AOP,即面向切面編程。在Spring框架上已經(jīng)存在很長時間了。
AspectJ,是一個基于AOP思想來實現(xiàn)的一個框架,它能提供ajc編譯器,將配置好的內(nèi)容在編譯階段寫進(jìn)源代碼中,以實現(xiàn)“織入”的操作。
要使用AspectJ框架有2種方式
1、直接在Gradle腳本編寫配置信息
源碼:https://github.com/wangzhzh/AutoTrackAspectJProject1
2、通過Gradle Plugin插件的形式,配置AspectJ框架
源碼:https://github.com/wangzhzh/AutoTrackAspectJProject2
這里介紹了如何使用Gradle Extentions來擴(kuò)展Gradle配置腳本。
用AspectJ框架實現(xiàn)埋點監(jiān)控
源碼:https://github.com/wangzhzh/AutoTrackAppClick5
AspectJ框架有缺點:
1、無法織入第三方庫
2、無法兼容Lambda語法
3、有兼容性問題,D8、Gradle4.X
6、ASM
Android應(yīng)用程序的打包流程有需要的自行查閱。Goodle提供了Transform API,用于.class文件打包成.dex文件之前實現(xiàn)想要的操作。ASM是Java字節(jié)碼操作和分析框架,可以通過ASM實現(xiàn)動態(tài)改變類或增強(qiáng)既有類的功能。如,在click方法后增加埋點記錄邏輯。
Gradle Transform操作例子:
源碼:https://github.com/wangzhzh/AutoTrackTransformProject
這里的實現(xiàn)是每次都是清除舊的構(gòu)建記錄,再新生成編譯后的代碼。
ASM核心類:ClassReader、ClassVisitor、AdviceAdapter
ClassVisitor會遍歷類中的所有成員。
用ASM框架實現(xiàn)埋點監(jiān)控
源碼:https://github.com/wangzhzh/AutoTrackAppClick6
ALOAD、ILOAD區(qū)別
ALOAD:指加載對象類型的參數(shù),如 UserEntity
ILOAD:指加載基礎(chǔ)類型的參數(shù),如 int、long、boolean等
7、8 Javassist、AST
這兩種方式不太好理解,自行查閱相關(guān)代碼。
源碼:https://github.com/wangzhzh/AutoTrackAppClick7
源碼:https://github.com/wangzhzh/AutoTrackAppClick8
綜上所述,最完美的解決方案是ASM,不用反射,沒有兼容性問題,語法又清晰。最終確定用ASM方式進(jìn)行埋點數(shù)據(jù)記錄。另外涉及到數(shù)據(jù)保存、清理、上報的邏輯,用Google的room進(jìn)行數(shù)據(jù)保存,定期清理已上報的數(shù)據(jù),上報網(wǎng)絡(luò)組件是基本的Http請求。