太恐怖了!移動開發APP 可視化埋點技術原理竟然是這樣的?! ...

0
回復
209
查看
打印 上一主題 下一主題
[復制鏈接]

23

主題

23

帖子

830

安幣

代碼手工藝人

Rank: 4

樓主
發表于 2019-12-10 17:00:01 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
如果對本篇文章感興趣,請前往,原文地址:http://www.1574304.live/blog-990284-82749.html

![](https://upload-images.jianshu.io/upload_images/1095900-fd25fcdf08314c9d.gif?imageMogr2/auto-orient/strip|imageView2/2/w/1240)###**一、背景**運營者能夠對用戶行為進行分析的前提,是對大量數據的掌握。在以往,這個數據通常是由開發者在控件點擊、頁面等事件中,一行行地編寫埋點代碼來完成數據收集的。然而傳統的操作模式每當升級改版時,開發和測試人員就需要重復不斷對代碼進行更新,整個流程耗時長,無法滿足業務的需求。為幫助開發者解決這一痛點,個推應用統計“個數”推出“可視化埋點”這一技術來更高效地實現這個這一過程?!皞€數”的可視化埋點靈活、方便,開發者不需對數據追蹤點添加任何代碼,只需要連接管理臺并圈選頁面中需要埋點的元素,即可添加隨時生效的界面追蹤點。本文將結合個數實踐經驗,對可視化埋點中的兩大關鍵技術點即**控件唯一標識和事件采集**進行分析并提供解決方案。###**二、可視化埋點關鍵技術點**可視化埋點的難點,或者說核心就是如何在開發者不編寫任何代碼的情況下,SDK 如何確定任意一個控件在該應用內的唯一性,以及如何監聽控件的點擊和頁面的切換。**標識**為了防止不同頁面中的控件標識重復出現,控件的唯一標識一般由頁面標識加上控件標識生成。**頁面標識生成**頁面標識可以直接使用頁面的名稱,即 Activity name。其獲取方式比較多,這里介紹一種比較通用的方法,即通過注冊 Application.ActivityLifecycleCallbacks ,開發者可以在以下生命周期的回調中,輕松地拿到當前的 Activity 對象。此方法適用于一個 Activity 并無 Fragment 存在的情形。代碼詳見下圖:![](https://upload-images.jianshu.io/upload_images/1095900-dc152b3eeff50303.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)獲取方式也是比較多,不過較于 Activity 的獲取會相對麻煩一些,因為系統沒有直接提供 API ,因而需要稍微轉個彎:通過 Gradle 插樁的方式,獲取 Fragment 的生命周期,以及 Fragment 實例對象:如果該應用的頁面存在一個 Activity 中嵌套多個 Fragment 的情況,單單一個 Activity name則可能無法精準地定位到某個頁面,因而還需要加上 Fragment 的名稱。Fragment的獲取可以通過 Gradle 插樁法來實現,即根據 Fragment 的生命周期來獲取Fragment 實例對象。![](https://upload-images.jianshu.io/upload_images/1095900-d96a316119831266.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)**1.2控件標識生成**理想的情況下頁面中的每個控件都有屬于自己的唯一 id,SDK 直接獲取控件的 id 當做控件標識即可。但現實情況卻是,一個頁面中往往存在多個相同 id 的控件,或者是沒有 id 的控件,比如 Listview 的 item ,開發者不可能給listview的每個item 設置不同的 id。因此需要轉變一下思路。我們可以從控件路徑這個除id 外比較獨特的性質著手來生成控件標識。開發者可以通過給控件的路徑加上控件角標的結構方式,生成控件的唯一標識。下圖是Github 上一個仿 B 站的應用。我們對這個應用進行一下控件樹分析。首先我們使用 Android Studio 自帶的 UI Automator Viewer 工具查看該頁面的布局結構:![](https://upload-images.jianshu.io/upload_images/1095900-3a68425a46181c2a.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)接下來,我們可以從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 的代理:![](https://upload-images.jianshu.io/upload_images/1095900-8a3009c801369461.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)當對應的控件被點擊時,系統就會自動調用設置過代理的方法,存儲或者上報對應數據。![](https://upload-images.jianshu.io/upload_images/1095900-5bd06c59738776f7.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)**Gradle 插樁的方式**Android Gradle 工具在1.5.0 版本后提供了 Transfrom API , 該API 允許第三方 Plugin 在打包 dex 文件之前的編譯過程中操作 .class 文件。在編譯期,開發者可以通過onClick、onItemClick等方法(詳見下圖)進行監聽,這相當于是正則匹配。當上述監聽的方法被編譯的時候,就可以將埋點的代理操作插入這些方法中,實現自動化埋點的流程。網上相關流程也是非常詳細,有興趣的可以自行搜索學習。![](https://upload-images.jianshu.io/upload_images/1095900-70d986a89c0c13c1.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)###**三、結語**以上就是APP端可視化埋點實現過程中的關鍵點,特別需要注意的是控件唯一標識那一塊,由于布局千變萬化,開發者針對很多特定的布局都需要采取對應的處理方式。據目前應用統計——個數這個產品只需要一行初始化代碼就可以自動幫助開發者采集包括頁面統計、事件埋點、新增活躍等多維度信息。最后對于程序員來說,要學習的知識內容、技術有太多太多,要想不被環境淘汰就只有不斷提升自己,**從來都是我們去適應環境,而不是環境來適應我們!**這里附上上述的技術體系圖相關的幾十套**騰訊、頭條、阿里、美團等公司19年的面試題**,把技術點整理成了視頻和PDF(實際上比預期多花了不少精力),包含**知識脈絡   諸多細節**,由于篇幅有限,這里以圖片的形式給大家展示一部分。**相信它會給大家帶來很多收獲:**![](https://upload-images.jianshu.io/upload_images/1095900-cb976892fb4ee64d.png?imageMogr2/auto-orient/strip|imageView2/2/w/479/format/webp)**上述【高清技術腦圖】以及【配套的架構技術PDF】可以 加我wx:X1524478394 免費獲取**> 當程序員容易,當一個優秀的程序員是需要不斷學習的,從初級程序員到高級程序員,從初級架構師到資深架構師,或者走向管理,從技術經理到技術總監,每個階段都需要掌握不同的能力。早早確定自己的職業方向,才能在工作和能力提升中甩開同齡人。  繼續閱讀全文



想在安卓巴士找到更多優質博文,可移步博客區

如果對本篇文章感興趣,請前往,
原文地址:
http://www.1574304.live/blog-990284-82749.html
分享到:  QQ好友和群 QQ空間 微信
收藏
收藏0
支持
支持0
反對
反對0
您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

領先的中文移動開發者社區
18620764416
7*24全天服務
意見反饋:[email protected]

掃一掃關注我們

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粵ICP備15117877號 )

在柳州学什么小吃赚钱