?導讀:全埋點數據采集技術,也叫無埋點、無碼埋點、無痕埋點、自動埋點。全埋點是指無需 Android 應用程序開發工程師寫代碼或者只寫少量的代碼,就能預先自動收集用戶的所有行為數據,然后就可以根據實際的業務分析需求從中篩選出所需行為數據并進行分析。作者:神策數據
如需轉載請聯系華章科技
全埋點采集的事件目前主要包括下面四種(事件名稱前面的 $ 符號,是指該事件是預置事件,與之對應的是自定義事件):
$AppStart 事件:是指應用程序啟動,同時包括冷啟動和熱啟動場景。熱啟動也就是指應用程序從后臺恢復。$AppEnd 事件:是指應用程序退出,包括應用程序的正常退出、按 Home 鍵進入后臺、應用程序被強殺、應用程序崩潰等場景。$AppViewScreen 事件:是指應用程序頁面瀏覽,對于 Android應用程序來說,就是指切換 Activity 或 Fragment。$AppClick 事件:是指應用程序控件點擊,也即 View 被點擊,比如點擊 Button、ListView 等。在采集的這四種事件當中,最重要并且采集難度最大的是 $AppClick 事件。
所以,全埋點的解決方案基本上也都是圍繞著如何采集 $AppClick 事件的。
對于 $AppClick 事件的全埋點整體解決思路,歸根結底,就是要自動的找到那個被點擊控件的點擊處理邏輯(我們后文也會叫原處理邏輯),然后再利用一定的技術原理,對原處理邏輯進行“攔截”,或者在原處理邏輯的執行前面或執行者后面“插入”相應的埋點代碼邏輯,從而達到自動埋點的效果。
至于如何做到自動“攔截” 控件的原處理邏輯,一般都是參考 Android 系統的事件處理機制來進行的。關于 Android 系統的事件處理機制,由于篇幅有限,不再詳述。
本文來主要介紹 $AppClick 全埋點方案:AST,更多全埋點方案請關注《Android 全埋點解決方案》一書。
01 關鍵技術1. APT
APT 是 ANNOTATION PROCESSING TOOL 的縮寫,即注解處理器,是一種處理注解的工具。確切的說它是JAVAC的一個工具,它用來在編譯時掃描和處理注解。注解處理器以JAVA代碼(或者編譯過的字節碼)作為輸入,生成 .JAVA文件作為輸出。簡單來說就是在編譯期,通過注解生成 .JAVA文件。
2. Element
自定義注解處理器,需要繼承 AbstractProcessor 類。而 AbstractProcessor 最重要的就是 process 方法。process 方法處理的核心是 Element 對象。
我們下面詳細的介紹一下 Element 對象。
Element的完整源碼如下。
package javax.lang.model.element;import java.lang.annotation.Annotation;import java.util.List;import java.util.Set;import javax.lang.model.AnnotatedConstruct;import javax.lang.model.type.TypeMirror;public interface Element extends AnnotatedConstruct { TypeMirror asType(); ElementKind getKind(); Set<Modifier> getModifiers(); Name getSimpleName(); Element getEnclosingElement(); List<? extends Element> getEnclosedElements(); boolean equals(Object var1); int hashCode(); List<? extends AnnotationMirror> getAnnotationMirrors(); <A extends Annotation> A getAnnotation(Class<A> var1); <R, P> R accept(ElementVisitor<R, P> var1, P var2);}從以上定義可以看出, Element 其實就是一個接口,它定義了外部可以調用的幾個方法。
我們下面簡單的介紹一下它規定的一些常用方法。
Element 有 5 個直接子類,它們分別代表一種特定類型的元素。五個子類各有各的用處并且有各種獨有的方法,在使用的時候可以強制將Element對象轉換成其中的任何一種,但是必須滿足轉換的條件,不然會拋出異常。
其中 TypeElement 和 VariableElement 是最核心的兩個 Element,也是我們下文會使用到的。
3. APT實例
我們下面來講解一個關于 APT 實例。
我們通過 APT 來實現一個功能,功能類似于 ButterKnife 中的 @BindView 注解。即通過對 View 變量的注解,實現對 View 的綁定(無需調用 findViewById 方法)。
完整的項目源碼可以參考:
://github.com/wangzhzh/AutoTrackAPTProject
4. AST
我們下面講解一下什么是 AST。
AST,是 Abstract Syntax Tree 的縮寫,即“抽象語法樹”,是編輯器對代碼的第一步加工之后的結果,是一個樹形式表示的源代碼。源代碼的每個元素映射到一個節點或子樹。
Java 的編譯過程可以分成三個階段,參考圖11-5。
▲圖11-5 編譯過程
第一階段:所有的源文件會被解析成語法樹;第二階段:調用注解處理器,即 APT 模塊。如果注解處理器產生了新的源文件,新的源文件也要參與編譯;第三階段:語法樹會被分析并轉化成類文件。02 原理概述編輯器對代碼處理的流程大概是:
JavaTXT->詞語法分析-> 生成AST ->語義分析 -> 編譯字節碼
通過操作AST,可以達到修改源代碼的功能。
可以在自定義注解處理器的 process 方法里,通過 roundEnvironment.getRootElements() 方法可以拿到所有的 Element 對象,通過 trees.getTree(element) 方法可以拿到對應的抽象語法樹(AST),然后我們自定義一個 TreeTranslator,在 visitMethodDef 里即可對方法進行判斷。
如果是目標處理方法,則通過 AST 框架的相關 API 即可插入埋點代碼,從而實現全埋點的效果。
03 案例下面以自動采集 Android 的 Button點擊事件為例,詳細介紹該方案的實現。對于其它控件的自動采集,后面會進行擴展。
完整的項目源碼可以參考:
://github.com/wangzhzh/AutoTrackAppClick8
04 缺點com.sun.tools.javac.tree 相關 API 語法晦澀,理解難度大,要求對編譯原理有一定的基礎;APT 無法掃描其他 module,導致 AST 無法處理其它 module;不支持 Lambda 語法;帶有返回值的方法,很難把埋點代碼插入到方法之后。關于作者:國內知名大數據公司神策數據出品,作者王灼洲是神策數據合肥研發中心負責人,有近10年Android開發經驗,開發和維護著知名商用開源 Android & iOS 數據埋點 SDK。 延伸閱讀《Android 全埋點解決方案》
推薦語:0年Andriod開發經驗專家撰寫,8種Android全埋點技術方案,附源碼。適讀人群:適用于初級、中級、高級水平的Android 開發工程師、技術經理、技術總監等。