1、背景面試
運營者可以對用戶行爲進行分析的前提,是對大量數據的掌握。在以往,這個數據一般是由開發者在控件點擊、頁面等事件中,一行行地編寫埋點代碼來完成數據收集的。然而傳統的操做模式每當升級改版時,開發和測試人員就須要重複不斷對代碼進行更新,整個流程耗時長,沒法知足業務的需求。工具
爲幫助開發者解決這一痛點,個推應用統計「個數」推出「可視化埋點」這一技術來更高效地實現這個這一過程。「個數」的可視化埋點靈活、方便,開發者不需對數據追蹤點添加任何代碼,只須要鏈接管理臺並圈選頁面中須要埋點的元素,便可添加隨時生效的界面追蹤點。佈局
本文將結合個數實踐經驗,對可視化埋點中的兩大關鍵技術點即控件惟一標識和事件採集進行分析並提供解決方案。學習
2、可視化埋點關鍵技術點測試
可視化埋點的難點,或者說核心就是如何在開發者不編寫任何代碼的狀況下,SDK 如何肯定任意一個控件在該應用內的惟一性,以及如何監聽控件的點擊和頁面的切換。ui
標識spa
爲了防止不一樣頁面中的控件標識重複出現,控件的惟一標識通常由頁面標識加上控件標識生成。3d
頁面標識生成代理
頁面標識能夠直接使用頁面的名稱,即 Activity name。其獲取方式比較多,這裏介紹一種比較通用的方法,即經過註冊 Application.ActivityLifecycleCallbacks ,開發者能夠在如下生命週期的回調中,輕鬆地拿到當前的 Activity 對象。此方法適用於一個 Activity 並沒有 Fragment 存在的情形。server
代碼詳見下圖:
獲取方式也是比較多,不過較於 Activity 的獲取會相對麻煩一些,由於系統沒有直接提供 API ,於是須要稍微轉個彎:經過 Gradle 插樁的方式,獲取 Fragment 的生命週期,以及 Fragment 實例對象:
若是該應用的頁面存在一個 Activity 中嵌套多個 Fragment 的狀況,單單一個 Activity name則可能沒法精準地定位到某個頁面,於是還須要加上 Fragment 的名稱。Fragment的獲取能夠經過 Gradle 插樁法來實現,即根據 Fragment 的生命週期來獲取Fragment 實例對象。
1.2控件標識生成
理想的狀況下頁面中的每一個控件都有屬於本身的惟一 id,SDK 直接獲取控件的 id 當作控件標識便可。但現實狀況倒是,一個頁面中每每存在多個相同 id 的控件,或者是沒有 id 的控件,好比 Listview 的 item ,開發者不可能給listview的每一個item 設置不一樣的 id。
所以須要轉變一下思路。咱們能夠從控件路徑這個除id 外比較獨特的性質着手來生成控件標識。開發者能夠經過給控件的路徑加上控件角標的結構方式,生成控件的惟一標識。下圖是Github 上一個仿 B 站的應用。咱們對這個應用進行一下控件樹分析。首先咱們使用 Android Studio 自帶的 UI Automator Viewer 工具查看該頁面的佈局結構:
接下來,咱們能夠從Application.ActivityLifecycleCallbacks 的回調中拿到 Activity 實例,再使用 activity.getWindow().getDecorView().getRootView() 方法來獲取當前頁面的控件樹。
例如圖中的文字控件是 TextView,且無兄弟佈局,則能夠標記爲 TextView[0] 。它的父佈局是 LinearLayout 且排在兄弟佈局中的第二位,那麼就能夠寫成是 LinearLayout[1],而後使用本身定義的符號拼接,像是 LinearLayout[1]/TextView[0] 。以後以此類推、循環遍歷、層層遞進,將全部通過的控件以及它們的下標都拼接起來,組成控件在該頁面中的惟一標識。
對於一些可複用的 View ,咱們則須要採起一些特殊處理。例如對於 RecyclerView、ListView、 ViewPager 等複用控件,咱們都須要採起不一樣的處理方式,去獲取當前 View 在該控件中的具體下標。若是沒有進行特殊處理,則會致使子控件錯位,數據統計不許確。
採集
在以往的處理中,若是須要知道一個按鈕的點擊次數,開發者就要在該控件的click事件中加入對應的打點代碼。這種重複勞做,無疑增長了開發者的開發負擔。對此,咱們能夠採用動態代理方式或Gradle 插樁方式來改善這個問題。
動態代理方式
使用安卓自帶的輔助功能 View.AccessibilityDelegate 。前文提到當頁面變化時,咱們能夠經過 Application.ActivityLifecycleCallbacks 獲取到 Activity 的實例對象,接着根據activity.getWindow().getDecorView().getRootView() 來獲取到控件樹。因爲控件樹可能會實時發生變化,咱們則須要經過 ViewTreeObserver.OnGlobalLayoutListener 的方法監聽視圖變化,從而在該回調中拿到變化的控件。接着咱們 要根據遞歸判斷該控件是否爲 ViewGroup、是否能夠點擊、是否可以顯示等,繼而給符合條件的 View 設置 sendAccessibilityEvent();此外,咱們還要在繼承了 View.AccessibilityDelegate 的定義類中,對如下這些方法添加 SDK 的代理:
當對應的控件被點擊時,系統就會自動調用設置過代理的方法,存儲或者上報對應數據。
Gradle 插樁的方式
Android Gradle 工具在1.5.0 版本後提供了 Transfrom API , 該API 容許第三方 Plugin 在打包 dex 文件以前的編譯過程當中操做 .class 文件。在編譯期,開發者能夠經過onClick、onItemClick等方法(詳見下圖)進行監聽,這至關因而正則匹配。
當上述監聽的方法被編譯的時候,就能夠將埋點的代理操做插入這些方法中,實現自動化埋點的流程。網上相關流程也是很是詳細,有興趣的能夠自行搜索學習。
3、結語
以上就是APP端可視化埋點實現過程當中的關鍵點,特別須要注意的是控件惟一標識那一塊,因爲佈局變幻無窮,開發者針對不少特定的佈局都須要採起對應的處理方式。
目前個推應用統計——個數這個產品只須要一行初始化代碼就能夠自動幫助開發者採集包括頁面統計、事件埋點、新增活躍等多維度信息。
藉着萬聖節,悄悄跟你說個恐怖的故事:除個推應用統計服務以外,VIP消息推送、用戶畫像,如今申請都可以避免費用一年!一鍵認證服務還能夠享受充10萬條送5萬條的優惠哦 !點擊https://www.getui.com/2019dev...,「碼「上申請吧!
行業前沿、面試寶典,更多技術乾貨,盡在個推技術學院。