老李分享:Android -自动化埋点 2
除了上述的事件,Android提供了一個OnTouchListener的監聽器,當事件傳遞到控件的時候,如果控件注冊了這個監聽器,則會執行監聽器中的onTouch方法。同時,如果它返回true,則事件也是不繼續向下傳遞了。
public?boolean?onTouch(View?v,?MotionEvent?event)上述的事件傳遞可以通過舉一個例子說明,假設一個界面上有一個Button按鈕,當我們touch down這個Button的時候,DOWN事件的傳遞如下:
Activity->dispatchTouchEvent???????Button->dispatchTouchEventButton->onTouchButton->onTouchEvent這里的每一步返回false,事件就不會向下傳遞。當我們touch up這個Button的時候,UP事件的傳遞如下:
Activity->dispatchTouchEvent???????Button->dispatchTouchEventButton->onTouchButton->onTouchEvent????Button->click可以看到,一個Button的click事件要經過上面幾個過程。如果要監聽一個Button的click事件,有一種思路是我們可以創建一個基類 BaseButton繼承自Button,在回調OnClickListener的地方加入攔截代碼。但是麻煩的是,點擊控件不一定是Button,可能 是其他TextView或者Layout之類的,Android中控件很多,我們要造很多控件基類,這樣應用中充滿的控件都必須是我們自己創建的控件,這 樣的設計是相當龐雜的。
那么我們考慮另外一種思路:讓創建的BaseActivity基類重寫Activity的dispatchTouchEvent方法,當touch button時,可以獲取到按下(DOWN)和抬起(UP)時產生的MotionEvent對象。這個MotionEvent對象有兩個方 法,getRawX()和getRawY(),通過這兩個方法我們可以獲取到“點擊位置”在界面中的坐標。同時,上文中提到,Activity的UI是層 層嵌套的,通過“根”view可以層層遍歷其下的子view以及所有子View上的控件,這些View和控件在屏幕中的坐標和寬高我們是可以獲取到的。好 了,這樣就可以搜索所有的子View或者控件的布局區域是否包含“點擊位置”,從而來判斷哪個View或控件被點擊。具體判斷可以通過如下代碼實現。
public?boolean?isInView(View?view,MotionEvent?event){int?clickX?=?event.getRawX();???int?clickY?=?event.getRawY();//如下的view表示Activity中的子View或者控件int[]?location?=?new?int[2];????view.getLocationOnScreen(location);??int?x?=?location[0];int?y?=?location[1];int?width?=?view.getWidth();int?height?=?view.getHeight();if?(clickX?<?x?||?clickX?>?(x?+?width)?||?clickY?<?y?||?clickY?>?(y?+?height))?{return?true;??//這個條件成立,則判斷這個view被點擊了}return?false;}自動化埋點的實現
綜上我們可以整理一下自動化埋點的思路。對于自動化埋點第一個功能,可以通過創建基類BaseActivity重寫Activity的所有的生命周期。對 于自動化埋點的第二個功能,實現方式是,通過重寫Activity的dispatchTouchEvent方法,點擊事件發生時,通過 MotionEvent對象獲取點擊位置坐標,然后遍歷Activity界面中所有的View(控件也都是View),判斷哪個View區域包含點擊位 置,從而判斷哪個View被點擊了。另外有個問題,當攔截到這些操作信息,如何將它放到一個統一的地方去處理呢?可以采用廣播的方式,將相關數據發送出 去,然后在一個BroadcastReceiver中統一處理埋點的log生成??慈缦麓a:
public?BaseActivity?extends?Activity{//其他的Activity生命周期重寫類似protected?void?onStart()?{super.onStart();LocalBroadcastManager?broadcastManager?=?LocalBroadcastManager.getInstance(this);Intent?intent?=?new?Intent(ACTIVITY_START);intent.putExtra(ACTIVITY_START,?event);broadcastManager.sendBroadcast(intent);}protected?boolean?dispatchTouchEvent(MotionEvent?ev)?{if?(event.getAction()?==?MotionEvent.ACTION_UP)?{LocalBroadcastManager?broadcastManager?=?LocalBroadcastManager.getInstance(this);Intent?intent?=?new?Intent(VIEW_CLICK);intent.putExtra(VIEW_CLICK,?event);broadcastManager.sendBroadcast(intent);}}}public?class?AutoMonitorReceiver?extends?BroadcastReceiver?{public?void?onReceive(Context?context,?Intent?intent)?{String?action?=?intent.getAction();if(action?==?VIEW_CLICK){MotionEvent?event?=?intent.getParcelableExtra(VIEW_CLICK);//1.遞歸遍歷Activity(就是Context)中的所有View,找出被點擊的ViewView?clickView?=?searchClickView(view,?event);//2.生成log記錄下來writeLog();?}else?if(action?==?ACTIVITY_START){//可以知道某個界面被打開了,然后記錄此次操作行為writeLog();}}private?View?searchClickView(View?view,?MotionEvent?event)?{View?clickView?=?null;if?(isInView(view,?event)?&&?view.getVisibility()?==?View.VISIBLE)?{??//這里一定要判斷View是可見的if?(view?instanceof?ViewGroup)?{????//遇到一些Layout之類的ViewGroup,繼續遍歷它下面的子ViewViewGroup?group?=?(ViewGroup)?view;for?(int?i?=?group.getChildCount()?-?1;?i?>=?0;?i--)?{View?chilView?=?group.getChildAt(i);clickView?=?searchClickView(chilView,?event);if?(clickView?!=?null)?{return?clickView;}}}clickView?=?view;}???return?clickView;}}轉載于:https://www.cnblogs.com/poptest/p/5113676.html
總結
以上是生活随笔為你收集整理的老李分享:Android -自动化埋点 2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Spring 基础篇三】属性注入与属性
- 下一篇: Android 关于“NetworkOn