Android全埋點(diǎn)解決方案讀書筆記(全)與最佳方案總結(jié)

原創(chuàng)不易,轉(zhuǎn)載請(qǐng)著名出處,謝謝

一. 全埋點(diǎn)概述

事件類型 事件定義
AppStart 應(yīng)用程序啟動(dòng),包含冷啟動(dòng)/熱啟動(dòng)
AppEnd 應(yīng)用程序退出,包含正常退出,home按下,程序強(qiáng)殺/崩潰
AppViewScreen 頁面瀏覽,包含切換Activity/Fragment
AppClick 控件點(diǎn)擊

1. Android View 類型

序號(hào) 控件名 監(jiān)聽方法
1 Button,CheckedTextView,TextView,ImageButton,ImageView View.OnClickListener
2 SeekBar SeekBar.OnSeekBarChangeListener
3 TabHost TabHost.OnTabChangeListener
4 RatingBar RatingBar.OnRatingBarChangeListener
5 CheckBox,SwitchCompat,RadioButton,ToggleButton,RadioGroup CompoundButton.OnCheckChangeListener
6 Spinner AdapterView.OnItemSelectListener
7 MenuItem 重寫 Activity的 onOptionItemSelect,onContextItemSelect
8 ListView,GridView AdapterView.OnItemSelectChangeListener
9 ExpandableListView ExpandableListView.OnChildClickListener,ExpandableListView.OnGroupClickListener
10 Dialog DialogInterface.OnClickListener,DialogInterface.OnMultiChoiceClickListener

2. View 綁定listener方式

序號(hào) 監(jiān)聽方法
1 代碼方式 - 直接 setOnClickListener 監(jiān)聽
2 xml - 中 android:onClick 綁定方法,在方法中監(jiān)聽
3 butterKnife - 注解方法 @OnClick(xxx) ,在方法中監(jiān)聽
4 lambda 方式 - setOnClickListener(v -> xxx)【aspectj不支持】
5 dataBinding - android:onclick ="xx:xxx" ,在指定的xxx方法中監(jiān)聽

二. AppViewScreen 全埋點(diǎn)方案

源碼:https://github.com/wangzhzh/AutoTrackAppViewScreen

1. Application.ActivityLifecycleCallbacks

  1. 通過此registerActivityLifecycleCallbacks里面監(jiān)聽到onActivityResume上報(bào)AppViewScreen數(shù)據(jù)。
  2. 上報(bào)數(shù)據(jù)有event,deviceId,properties,time。
  3. 上報(bào)數(shù)據(jù)properties包含有appName,model,os-version,app-version,maunfacturer,width,height,os,lib-version,lib,activity。

2. 權(quán)限問題 READ_CONTACTS

6.0之后執(zhí)行運(yùn)行時(shí)權(quán)限回調(diào)onRequestPermissionResult 之后會(huì)再次執(zhí)行onResume導(dǎo)致頁面重復(fù)上報(bào)。

  • 解決措施
    制作ignore忽略類,在onRequestPermissionResult 回調(diào)中加入addIgnoreActivity,在onStop中 移除 removeIgnoreActivity,不上報(bào)的類也可以添加進(jìn)去,在上報(bào)之前判斷未忽略才執(zhí)行上報(bào)。

3. 頁面名稱采集

采集按照如下優(yōu)先級(jí):

  1. activity.getTitle
  2. sdkInt>=11 ,直接獲取getToolbarTitle{activity.getActionBar.getTitle/appCompatAct.getActionBar.gettitle}
  3. activity.packageManager.activityInfo.loadLabel

三. AppStart,AppEnd 全埋點(diǎn)方案

源碼:https://github.com/wangzhzh/AutoTrackAppStartAppEnd

1. 原理

  • AppStart : Application.registerActivityLifecycleCallbacks方法onActivityStarted中,執(zhí)行上報(bào),并通過ContentProvider+SQLite存儲(chǔ)標(biāo)記(作用是解決跨進(jìn)程數(shù)據(jù)共享問題,通過ContentObserver監(jiān)聽新進(jìn)頁面,標(biāo)記變化,如果在30s內(nèi),就取消上個(gè)頁面退出倒計(jì)時(shí),如果超30s,就執(zhí)行AppEnd上報(bào))

  • AppEnd : sdk初始化的時(shí)候創(chuàng)建定時(shí)器,Application.registerActivityLifecycleCallbacks方法onActivityStop時(shí),開啟定時(shí)器。30s后無新頁面進(jìn)入,執(zhí)行上報(bào),程序奔潰,強(qiáng)殺退出,下次進(jìn)入頁面需要補(bǔ)上報(bào) AppEnd

2. 缺點(diǎn)

因?yàn)槌绦虮紳ⅲ瑥?qiáng)殺,后面需要補(bǔ)上報(bào) AppEnd,如果用戶后面不在使用程序,或卸載程序,會(huì)導(dǎo)致 AppEnd 丟失

四. AppClick 全埋點(diǎn)方案 - 1:代理 View.OnClickenerListener

源碼:https://github.com/wangzhzh/AutoTrackAppClick1

1. 原理

在Application.registerActivityLifecycleCallbacks方法onActivityResume中,通過activity.getwindow.getDecorView獲取到其rootView,然后遞歸遍歷所有子控件,并對(duì)所有子控件的點(diǎn)擊事件設(shè)置代理攔截wrapperOnClickListener,其中有無點(diǎn)擊事件,通過反射View里面的mOnClickListener屬性判斷。

注意:

  1. 根據(jù)層級(jí)關(guān)系,DecorView是最頂層,子控件包含MenuItem及R.layout.content容器,所以為了能夠監(jiān)聽到MenuItem,取最頂層DecorView,不要取R.layout.content作為rootView,(與此同時(shí),獲取text需要加MenuItem類型的判斷)
  2. 為解決頁面中動(dòng)態(tài)添加控件問題,所以引入ViewTreeObserver.OnGlobalLayoutListener,所以此時(shí)邏輯變更了,在registerActivityLifecycleCallbacks方法onActivityCreate中創(chuàng)建OnGlobalLayoutListener監(jiān)聽器及監(jiān)聽器中遍歷綁定所有控件,在onActivityResume添加監(jiān)聽,在onActivityStop中移除監(jiān)聽

2. 上傳字段

  • element_type: view.getclass.getCanonicalName
  • element_id: 獲取view的id
  • element_content: 獲取view的text
  • activity: 包名+類名(通過context獲取包名,如果是contextWrapper類型,需要遞歸獲取getBaseContext,直至找到activity返回包名)

3. 拓展

控件名 content獲取 監(jiān)聽方法(反射+代理)
Button,CheckedTextView,TextView getText View.OnClickListener
ImageButton,ImageView getContentDescription View.OnClickListener
CheckBox,SwitchCompat,RadioButton,ToggleButton getText CompoundButton.OnCheckChangeListener
RadioGroup 獲取選中的控件,在getText CompoundButton.OnCheckChangeListener
RatingBar getRating RatingBar.OnRatingBarChangeListener
SeekBar getPrgress SeekBar.OnSeekBarChangeListener
TabHost 遍歷子控件,拼接文本 TabHost.OnTabChangeListener
Spinner 遍歷子控件,拼接文本 AdapterView.OnItemSelectChangeListener
MenuItem getMenuText 重寫 Activity的 onOptionItemSelect,onContextItemSelect
ListView,GridView getPosition AdapterView.OnItemSelectChangeListener
ExpandableListView Group position: child position ExpandableListView.OnChildClickListener,ExpandableListView.OnGroupClickListener
Dialog getText 獲取到rootView之后,在遍歷所有子控件,show添加/dismiss移除OnGlobalListener監(jiān)聽,點(diǎn)擊代理 DialogInterface.OnClickListener,DialogInterface.OnMultiChoiceClickListener

五. AppClick 全埋點(diǎn)方案 - 2:代理 Window.CallBack

源碼:https://github.com/wangzhzh/AutoTrackAppClick2

1. 原理

Application.registerActivityLifecycleCallbacks方法onActivityCreate中,通過activity.getWindow.getcallBack,然后設(shè)置代理wrapperWindowCallback,通過這個(gè)代理類的dispatchTouchEvent,確定點(diǎn)擊的位置,然后從控件列表集合中找到具體的控件,插入埋點(diǎn)代碼。

判斷控件是否是集合中的哪個(gè)控件,需要滿足的條件:

  1. view.visible==view.visible
  2. view.isClickable==true
  3. MotionEvent的x,y坐標(biāo)必須處于view內(nèi)部

2. 拓展

控件名 判斷規(guī)則(默認(rèn)滿足上面1,2,3條件)
RatingBar 4.view是ratingBar類型
SeekBar 4.view是SeekBar類型
Spinner 采用代理方式處理,代理 dapterView.OnItemSelectChangeListener
ListView,GridView 采用代理方式處理,代理 ExpandableListView.OnChildClickListener,ExpandableListView.OnGroupClickListener

六. AppClick 全埋點(diǎn)方案 - 3:代理 View.AccessibilityDelegate

源碼:https://github.com/wangzhzh/AutoTrackAppClick3

1. 原理

在Application.registerActivityLifecycleCallbacks方法onActivityResume中,通過activity.getwindow.getDecorView獲取到其rootView,然后遞歸遍歷所有子控件,并對(duì)所有子控件設(shè)置代理攔截mAccessibilityEvent,埋點(diǎn)代碼就在其回調(diào)方法中處理。

2. 拓展

ratingBar/SeekBar/Spinner/ListView,GradView/ExpandableListView 均與之前《第四章View.OnClickenerListener》反射+動(dòng)態(tài)代理方案一致

3. 缺點(diǎn)

  1. 使用反射,效率低,有版本兼容問題
  2. 需要開啟輔助功能,部分Android Rom機(jī)型上可能會(huì)失效

七. AppClick 全埋點(diǎn)方案 - 4:透明層

源碼:https://github.com/wangzhzh/AutoTrackAppClick4

1. 原理

在activity的最上層添加一個(gè)透明的View,然后重寫透明view的onTouchEvent,從里面取出xy位置,判斷控件集合的具體控件,然后使用wrapperOnClickListener代理其mOnclickListener對(duì)象,并在代理類中實(shí)現(xiàn)埋點(diǎn)上報(bào)。

透明層條件:

  1. width/height需是layout.MATCH_PARENT
  2. 設(shè)置透明層在最上層,view.setElevation(xxx,999f)
  3. decorView.addView(xxx)

判斷控件是否在控件集合中,與之前《第六章View.AccessibilityDelegate》的尋找方法一致

2. 拓展

與《第五章 Window.CallBack》方案一致

七. AppClick 全埋點(diǎn)方案 - 5:Aspectj

源碼:https://github.com/wangzhzh/AutoTrackAppClick5

1. Aspectj

AOP 面向切面編程,可實(shí)現(xiàn)的有日志埋點(diǎn),性能監(jiān)控,動(dòng)態(tài)權(quán)限控制,代碼調(diào)試
Aspectj 使用ajc編譯器,在編譯期把代碼插入目標(biāo)程序中
Aspectj簡(jiǎn)單使用:Aspectj簡(jiǎn)單使用

使用AspectJ的2種方式:

  1. 簡(jiǎn)單的配置Aspectj:https://github.com/wangzhzh/AutoTrackAspectJProject1
  2. 自定義Gradle Plugin:https://github.com/wangzhzh/AutoTrackAspectJProject2

2. 擴(kuò)展View屬性

通過給控件setTag(int,object)的方式支持拓展,后續(xù)從view中取出這個(gè)值使用,但是為了保證tag的key不重復(fù),需要在xml中定義資源id,使用時(shí)就使用它即可

3. 無法采集情況

無法采集的情況 解決思路 aspectj代碼
butterknife的onClick注解綁定的事件 新增對(duì)onClick有參數(shù)情況的切入點(diǎn),無參數(shù)暫不考慮 @After("execution(@butterKnife.onclick **(android.view.View))")
xml android:onclick屬性綁定的事件 新增一個(gè)注解,然后加在此xml指定的方法上 @After("execution(@xxx **(android.view.View))")
MenuItem的點(diǎn)擊事件 新增2個(gè)menuItem監(jiān)聽的2方法 @After("execution(@android.app.Activity.onOptionItemSelected(android.view.MenuItem))") @After("execution(@android.app.Activity.onContextItemSelected(android.view.MenuItem))")
設(shè)置onclickListener使用了lambda語法 aspectj暫不支持lambda語法,所以無法解決

4. 拓展

控件名 aspectj代碼
AlertDialog @After("execution(@android.content.dialogInterface.onClickListener.onClick(android.content.dialogInterface,int))") @After("execution(@android.content.dialogInterface.onMultiChoiceClickistener.onClick(android.content.dialogInterface,int,Boolean))")
CheckBox,SwitchCompat,RadioButton,ToggleButton,RadioGroup @After("execution(@android.widget.CompoundButton.OnCheckChangeListener.onCheckChanged(android.widget.CompoundButton,Boolean))")
RatingBar @After("execution(@android.widget.RatingBar.OnRatingBarChangeListener.onRatingChanged(android.widget.RatingBar,float,Boolean))")
SeekBar @After("execution(@android.widget.SeekBar.OnSeekBarChangeListener.onStopTrackingTouch(android.widget.RatingBar,float,Boolean))")
Spinner @After("execution(@android.widget.AdapterView.OnItemSelectListener.onItemSelected(android.widget.AdapterView,android.view.View,int,long))")
TabHost @After("execution(@android.widget.TabHost.OnTabChangeListener.onTabChanged(String))")
ListView,GridView @After("execution(@android.widget.AdapterView.OnItemSelectChangeListener.onItemClick(android.widget.AdapterView,android.view.View,int,long))")
ExpandableListView @After("execution(@android.widget.ExpandableListView.OnChildClickListener.onChildClick(android.widget.ExpandableListView,android.view.View,int,long))") @After("execution(@android.widget.ExpandableListView.OnGroupClickListener.onGroupClick(android.widget.ExpandableListView,android.view.View,int,long))")

5. 缺點(diǎn)

  1. 無法織入第三方庫
  2. 無法兼容Lambda語法
  3. 有兼容性問題,D8、Gradle4.X

七. AppClick 全埋點(diǎn)方案 - 6:ASM

1. ASM

Android gradle 1.5.0之后,提供了transfrom API ,允許第三方插件形式,在安卓打包過程中操作.class文件,遍歷類,jar包等,在此過程中可再使用字節(jié)碼操作工具ASM去操作,去訪問具體的類,從類中讀取類名,方法,屬性等,然后通過字節(jié)碼指令去修改原有的類(例如:訪問到onClick方法,并在方法結(jié)束之前加一段埋點(diǎn)上報(bào)代碼),然后在將修改好的類,繼續(xù)執(zhí)行打包task,后續(xù)apk中就有了此上報(bào)邏輯。

涉及到的2個(gè)技術(shù)點(diǎn):

2. 無法采集情況

無法采集的情況 解決思路 ASM代碼
xml android:onclick屬性綁定的事件 新增一個(gè)注解,然后加在此xml指定的方法上,繼續(xù)visitorAnnotation中找到此注解,設(shè)置標(biāo)識(shí),并在此方法結(jié)束之后插入埋點(diǎn)代碼 isFlag=true&&desc=='(Landroid/view/View;)V'

4. 拓展

所有的操作都是在方法訪問器,結(jié)束方法中判斷是否達(dá)到條件,滿足則加入埋點(diǎn)字節(jié)碼

控件名 ASM判斷代碼
AlertDialog mInterface.conteins('android/content/DialogInterfaceOnclickListener')&&nameDesc=='onClick(Landroid/content/DialogInterface;I)V' mInterface.conteins('android/content/DialogInterfaceOnMultichoiceclickListener')&&nameDesc=='onClick(Landroid/content/DialogInterface;IZ)V'
MenuItem nameDesc=='onContextItemSelected(Landroid/view/MenuItem;Z)V' 或 nameDesc=='onOptionsItemSelected(Landroid/view/MenuItem;Z)V'
CheckBox,SwitchCompat,RadioButton,ToggleButton,RadioGroup mInterface.conteins('android/widget/CompoundButton$OnCheckChangeListener')&&nameDesc=='onCheckChanged(Landroid/content/CompoundButton;Z)V'
RatingBar mInterface.conteins('android/widget/RatingBar$OnRatingBarChangeListener')&&nameDesc=='onRatingChanged(Landroid/content/RatingBar;FZ)V'
SeekBar mInterface.conteins('android/widget/SeekBar$OnSeekBarChangeListener')&&nameDesc=='onStopTrackingTouch(Landroid/content/SeekBar;)V'
Spinner mInterface.conteins('android/widget/AdapterView$OnItemSelectListener')&&nameDesc=='onItemSelected(Landroid/content/AdapterView;Landroid/view/View;IJ)V
TabHost mInterface.conteins('android/widget/TabHost$OnTabChangeListener')&&nameDesc=='onTabChanged(Ljava/lang/String;)V
ListView,GridView mInterface.conteins('android/widget/AdapterView$OnItemClickListener')&&nameDesc=='onItemClick(Landroid/content/AdapterView;Landroid/view/View;IJ)V
ExpandableListView mInterface.conteins('android/widget/ExpandableListViewOnChildClickListener')&&nameDesc=='onChildClick(Landroid/content/ExpandableListView;Landroid/view/View;IIJ)Z) mInterface.conteins('android/widget/ExpandableListViewOnGroupClickListener')&&nameDesc=='onGroupClick(Landroid/content/ExpandableListView;Landroid/view/View;IJ)Z

七. AppClick 全埋點(diǎn)方案 - 7:Javassist

1. javassist

與ASM類似,為字節(jié)碼操作工具。那么處理流程也是通過transfrom遍歷文件找到指定類,然后通過 javassist處理指定文件,實(shí)現(xiàn)代碼注入。

2. 拓展

所有的操作都是在獲取到所有接口數(shù)組,遍歷方法,斷是否達(dá)到條件,滿足則通過method.insertAfter加入埋點(diǎn)字節(jié)碼

控件名 javassist判斷代碼(nameDesc=method.name+emthod.getSignature))
xml android:onclick屬性綁定的事件 新增一個(gè)注解,然后加在此xml指定的方法上。annotation== xxx && 'currentMethod.getSignature=='(Landroid/view/View;)V''
AlertDialog mInterface.conteins('android/content/DialogInterfaceOnclickListener')&&nameDesc=='onClick(Landroid/content/DialogInterface;I)V' mInterface.conteins('android/content/DialogInterfaceOnMultichoiceclickListener')&&nameDesc=='onClick(Landroid/content/DialogInterface;IZ)V'
MenuItem nameDesc=='onContextItemSelected(Landroid/view/MenuItem;Z)V' 或 nameDesc=='onOptionsItemSelected(Landroid/view/MenuItem;Z)V'
CheckBox,SwitchCompat,RadioButton,ToggleButton,RadioGroup mInterface.conteins('android/widget/CompoundButton$OnCheckChangeListener')&&nameDesc=='onCheckChanged(Landroid/content/CompoundButton;Z)V'
RatingBar mInterface.conteins('android/widget/RatingBar$OnRatingBarChangeListener')&&nameDesc=='onRatingChanged(Landroid/content/RatingBar;FZ)V'
SeekBar mInterface.conteins('android/widget/SeekBar$OnSeekBarChangeListener')&&nameDesc=='onStopTrackingTouch(Landroid/content/SeekBar;)V'
Spinner mInterface.conteins('android/widget/AdapterView$OnItemSelectChangeListener')&&nameDesc=='onItemSelected(Landroid/content/AdapterView;Landroid/view/View;IJ)V
TabHost mInterface.conteins('android/widget/TabHost$OnTabChangeListener')&&nameDesc=='onTabChanged(Ljava/lang/String;)V
ListView,GridView mInterface.conteins('android/widget/AdapterView$OnItemClickListener')&&nameDesc=='onItemClick(Landroid/content/AdapterView;Landroid/view/View;IJ)V
ExpandableListView mInterface.conteins('android/widget/ExpandableListViewOnChildClickListener')&&nameDesc=='onChildClick(Landroid/content/ExpandableListView;Landroid/view/View;IIJ)Z) mInterface.conteins('android/widget/ExpandableListViewOnGroupClickListener')&&nameDesc=='onGroupClick(Landroid/content/ExpandableListView;Landroid/view/View;IJ)Z

八. AppClick 全埋點(diǎn)方案 - 8:AST

源碼:https://github.com/wangzhzh/AutoTrackAppClick8

1. APT

  • APT
    APT 簡(jiǎn)單api
    實(shí)例:https://github.com/wangzhzh/AutoTrackAPTProject
    實(shí)質(zhì)就是對(duì)頁面某個(gè)控件添加注解,然后此注解生成器會(huì)編譯時(shí)生成添加了注解的類的輔助埋點(diǎn)上報(bào)類,在registerActivityLifecycleCallbacks的創(chuàng)建方法會(huì)找到此注解類,然后執(zhí)行上報(bào)邏輯

2. AST

抽象語法樹,用樹的形式表示源代碼,源代碼每個(gè)元素映射到一個(gè)節(jié)點(diǎn)或子樹。

編譯器對(duì)代碼的處理流程是:JavaTxt->詞語法分析->生成AST->語義分析->編譯字節(jié)碼,通過操作AST,達(dá)到修改源代碼目的。

具體流程:

  1. 注解處理器的process方法
  2. element=roundEnvironment.getRootElements
  3. tree=trees.getTree(element)
  4. 自定義一個(gè)TreeTranslator,執(zhí)行tree.accept(this)
  5. 在TreeTranslator的visitMethodDef找到指定方法,通過AST框架插入埋點(diǎn)代碼

3. 無法采集情況

無法采集的情況 解決思路 AST代碼
butterknife的onClick注解綁定的事件 AST遍歷注解時(shí)判斷@OnClick,且方法是onClick,無返回void,參數(shù)1個(gè) jcMethodDecl.getName==onClick&&jcMethodDecl.getParameters==void&&jcMethodDecl.getParameters.size==1
xml android:onclick屬性綁定的事件 新增一個(gè)注解,然后加在此xml指定的方法上 jcMethodDecl.getName==onClick&&jcMethodDecl.getParameters==void&&jcMethodDecl.getParameters.size==1
設(shè)置onclickListener使用了lambda語法 AST暫不支持lambda語法,所以無法解決

4. 拓展

主要根據(jù)返回值,方法名,方法參數(shù)個(gè)數(shù)及類型判斷,故封裝一個(gè)公用類統(tǒng)一判斷

控件名 AST代碼
AlertDialog 'onclick,void,Collections.singletonList(View),After' 'onclick,void,Arrays.asList(dialogInterface,int),After' 'onclick,void,Arrays.asList(dialogInterface,int,boolean),After'
MenuItem 'onOptionsItemSelected,boolean,Collections.singletonList(MenuItem),After' 'onContextItemSelected,boolean,Collections.singletonList(MenuItem),After'
CheckBox,SwitchCompat,RadioButton,ToggleButton,RadioGroup 'onCheckedChanged.void,Arrays.asList(CompoundButton,boolean),After'
RatingBar 'onRatingChanged,vpid,Arrays.asList(RatingBar,boolean),After'
SeekBar 'onStopTrackingTouch,void,Collections.singletonList(SeekBar),After'
Spinner 'onItemSelected,void,Arrays.asList(AdapterView<?>,View,int,long),After'
TabHost 'onTabChanged,void,Collections.singletonList(String),After
ListView,GridView 'onItemClick,void,Arrays.asList(AdapterView<?>,View,int,long),After'
ExpandableListView 'onGroupClick,boolean,Arrays.asList(ExpandableListView,View,int,long),Before' 'onChildClick,boolean,Arrays.asList(ExpandableListView,View,int,int,long),Before'

5. 缺點(diǎn)

  1. com.sun.tools.javac.tree APi語法晦澀,理解難度大
  2. APT無法掃描其他Module
  3. 不支持lambda語法
  4. 有返回值的方法,很難把埋點(diǎn)代碼插入方法之后

最佳方案總結(jié)

由于本人曾參與公司埋點(diǎn)SDK的研發(fā),所以對(duì)其有一套自己的理解和感悟,總結(jié)了一種最佳的方案,其方案如下

1. 上報(bào)事件的方案選擇

  • 點(diǎn)擊事件,上報(bào)方案選擇
    使用asm的方案是最好,最簡(jiǎn)單的,不會(huì)影響運(yùn)行時(shí)的時(shí)間,直接執(zhí)行點(diǎn)擊攔截上報(bào)

  • 頁面進(jìn)入/離開事件,上報(bào)方案選擇
    如果是activity的頁面進(jìn)入離開,直接通過Application.registerActivityLifecycleCallbacks可以直接監(jiān)聽上報(bào)。

    如果希望fragment/dialog/dialogFragment/popupwindow也可以上報(bào),可以制作他們的基類,并在基類的進(jìn)入離開,加入埋點(diǎn)上報(bào)代碼,制作transfrom 插件,通過asm方式去替換父類,注意:(此處不僅僅是通過類訪問器找到父類,簡(jiǎn)單的替換父類,還需要導(dǎo)入常量池修改庫替換常量池里面的父類,達(dá)到構(gòu)造方法也同步修改,否則修改失效)

  • 冷熱啟動(dòng)事件,上報(bào)方案選擇
    通過Application.registerActivityLifecycleCallbacks統(tǒng)計(jì)activity的有無的個(gè)數(shù),統(tǒng)計(jì)冷熱啟動(dòng)狀態(tài),執(zhí)行上報(bào)

  • 前臺(tái),后臺(tái)事件,上報(bào)方案選擇
    可使用此書中的方案,開啟倒計(jì)時(shí)30s,或者直接根據(jù)registerActivityLifecycleCallbacks統(tǒng)計(jì)當(dāng)前activity的狀態(tài)判斷也可,根據(jù)業(yè)務(wù)而定

  • 曝光/業(yè)務(wù)/xxx上報(bào)
    直接在上報(bào)sdk中提供上報(bào)方法即可

2. 處理流程

  • 構(gòu)造上報(bào)對(duì)象:sdk需創(chuàng)建線程池,所有的上報(bào)都應(yīng)該在線程池中執(zhí)行

  • 加入消息隊(duì)列:創(chuàng)建handler線程,使用此線程隊(duì)列保證消息的次序,待上報(bào)在線程池構(gòu)造成功具體的上報(bào)對(duì)象,統(tǒng)一封裝成消息,發(fā)送到消息隊(duì)列

  • 存入數(shù)據(jù)庫:消息隊(duì)列取出消息,執(zhí)行插入數(shù)據(jù)庫操作,并加入判斷100條,執(zhí)行上報(bào),或者3分鐘上報(bào)數(shù)據(jù)庫的上報(bào)數(shù)據(jù)

  • 執(zhí)行上報(bào):從數(shù)據(jù)庫取出消息,執(zhí)行okHttp的上報(bào),并且處理上報(bào)成功刪除數(shù)據(jù)庫數(shù)據(jù),及重試機(jī)制

3. transfrom 編譯優(yōu)化

  • 開啟增量編譯,處理好增量編譯
  • 創(chuàng)建線程池,在線程池中執(zhí)行遍歷文件,jar,提高同步編譯速度
  • 設(shè)置debug不開啟編譯,release開啟編譯,類似的動(dòng)態(tài)配置開關(guān),解決不需要此編譯項(xiàng)不讓其拉低apk編譯速度
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,143評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,416評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,940評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,170評(píng)論 0 287
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,709評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,597評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,784評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評(píng)論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,029評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評(píng)論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,403評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,746評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容