從去年和朋友一起做小程序開始,我開始對于產品的運營有了一個新的認知,今年又買了一本《數據化運營:系統方法與實踐案例》讓我的思維開始從原來的技術型和交互設計型開始慢慢接觸數據運營的概念。關于整體的方案還正在寫,這個是其中關于統計數據收集關于埋點技術的一部分。
由于我自身只接觸過iOS的Swift開發,但對于Android開發不太了解,而市場上關于埋點開發的書籍只找到了一本神策數據出的《Android全埋點解決方案》一書,而且是今年剛剛出版的,只好買了這本書去請教了Android開發同事,大致對于埋點開發的原理做了基礎的調研,也讓自己對于實現有了一點了解。
下文內容即來自于對書中內容的總結和從開發人員了解到的解釋,對于代碼實現部分不涉及而且我也只能以其他語言的基礎去理解Android,難免會露怯。
首先先解釋一下View
這是我的小程序的其中一個界面
這個頁面的所有內容都是由控件組成的,所有可點擊的控件都對應一個事件處理代碼,埋點統計即是對所有這些事件的監控。
Android的四種事件
----
$AppStart事件:應用程序啟動,同時包括冷熱啟動
$AppEnd事件:應用程序退出,包括正常退出、進入后臺、被強殺、崩潰
$AppViewScreen事件:頁面瀏覽,對于Android應用程序來說,就是指切換Activity或Fragment
$AppClick事件:控件的點擊,即View被點擊,包括Button、ListView等
這四個事件中,前三個比較簡單,而圍繞AppClick事件,全埋點即對AppClick事件進行攔截或者插入相關埋點代碼,按照攔截或者插入的時間的不同,分為兩種方式,每種方式有四個方案,也即是有八種不同的埋點方案AspectJ\ASM\Javassist\AST\View.OnClickListener代理\Window.Callback代理\View.AccessibilityDelegate代理\透明層。
靜態代理AspectJ\ASM\Javassist\AST
------------
Android的開發周期
1、編寫代碼
2、編譯代碼得到Package
3、安裝App
4、運行App
其中編譯代碼期間的流程是javaCode->.java->.class->.dex,AspectJ\ASM\Javassist\AST即是對這個編譯過程不同階段的處理,大致的處理方式就是開發者只需要對于代碼塊進行簡單的注解或者說由SDK遍歷去自動添加注解,然后在編譯過程中通過插件的形式對于開發者代碼進行改寫加入自己的統計代碼,這樣不會對源碼產生污染,又可以獲得比動態代理更好的性能。
動態代理
------------
動態代理即是在App運行過程中對于系統的方法進行代理,比如App中的控件點擊都會調用View.OnClickListener,動態代理就相當于接管了這個系統方法,然后在其中加入自己的統計代碼,每一次控件點擊調用View.OnClickListene的同時也會運行統計代碼來上傳用戶行為數據。
AppStart和AppEnd事件的判定
----------------
首先注冊一個Appication.ActivityLifecycleCallbacks回調用來監聽Activity的生命周期,頁面退出時啟動一個倒計時,如果沒有新頁面進來則觸發AppEnd事件,當頁面啟動時,判斷與上個頁面的退出事件間隔是否超過倒計時定義的時間,如果沒超過則觸發AppViewScreen事件,如果超過,首先判斷之前是否觸發了AppEnd事件,如果沒有則先觸發AppEnd事件,然后再觸發AppStart和AppViewScreen事件
AppViewScreen事件的判定
-------------
通過Application的內部接口ActivityLifeycleCallbacks提供的一些回調方法。
AppClick事件的判定
--------------
在這里只列出一種動態代理方法View.OnClickListener,其他的還是各自買書看吧。
在應用程序自定義的Application對象的OnCreate()方法中初始化埋點SDK,并傳入當前Application對象,在拿到Application對象后,通過registerActivityLifecycleCallback方法來注冊Appication.ActivityLifecycleCallbacks回調,在Appication.ActivityLifecycleCallbacks的onActivityResumed回調方法中,拿到當前正在顯示的Activity實例,通過activity.findViewById(android.R.id.content)方法就可以拿到整個內容區域對應的View,然后再逐層遍歷這個RootView,并判斷當前View是否設置了mOnClickListener對象,如果已設置mOnClickListener對象并且mOnClickListener又不是我們自定義的WrapperOnClickListener類型,則通過WrapperOnClickListener代理當前View設置的mOnClickListener,WrapperOnClickListener是統計SDK自定義的一個類,它實現了View.OnClickListener接口,在WrapperOnClickListener的onClick方法里會先調用View的原有mOnClickListener處理邏輯,然后再調用埋點代碼,既可以實現自動埋點的效果。