1. 程式人生 > >Android視覺化埋點(無埋點)的具體實現

Android視覺化埋點(無埋點)的具體實現

Android埋點技術深入探究

上一篇文章提到的無埋點技術在實際應用中有以下幾個問題需要處理。
大綱:
【1】控制元件的唯一標識問題怎麼處理。
【2】當控制元件處於可滑動的元件內或者整個介面就是一個可滑動的View中時位置如何確定。
【3】Fragment中如何得到觸控點的座標。
【4】Activity介面留存時間。

第一個問題:控制元件的唯一標識問題,上一篇文章也是參考了其他的部落格,說用控制元件的路徑來標識。這種方式先不說獲取到正確的路徑就是一件比較難處理的事情,而且伺服器端制定埋點位置時需要考慮不同版本的路徑不一樣,修改了佈局檔案後路徑就需要更新。同時考慮到95%以上需要埋點的控制元件都是設定了id的,不會因為埋點而故意加id,所以用控制元件的id做唯一標識。
第二個問題:因為之前使用了View的getHitRect()方法獲取view的位置座標,當滑動後坐標不準確了,參考資料後發現可以使用getGlobalVisibleRect()方法。參考:

http://stackoverflow.com/questions/13927718/view-gethitrectrect-not-working
第三個問題:因為Fragment中沒有dispatchTouchEvent()方法,所以這裡解決方法是定義一個介面,將Activity中得到的x,y座標傳遞給Fragment,然後Fragment中自己尋找View,完成埋點。
第四個問題:在onCreate()中獲取開始時間,在onPause中獲取結束時間。

還是給一個Demo輔助說明,這裡將埋點定義在基類中,更符合實際生產環境。
下面上程式碼:
在onCreate中做了兩件事,一是記錄進入的Activity並計時;二是初始化埋點列表,在實際中埋點列表資料通過伺服器獲取。

    @Override
    protected void onCreate(Bundle savedInstance){
        super.onCreate(savedInstance);
        startTime = System.currentTimeMillis();
        Log.v("out" , "進入了:"+(Activity)this);
        /*初始化一個需要埋點的列表*/
        ids.add(R.id.login);
        ids.add(R.id.register);
        ids.add
(R.id.register_hidden); ids.add(R.id.man); ids.add(R.id.woman); ids.add(R.id.seekbar); ids.add(R.id.checkbox); ids.add(R.id.img); ids.add(R.id.last); ids.add(R.id.fragment_a_tv_login); ids.add(R.id.fragment_a_tv_register); ids.add(R.id.left); }

然後是設定介面回撥,作用是將點選座標回傳給Fragment。

    public void setDispatchTouchEventable(DispatchTouchEventable dispatchTouchEventable){
        this.dispatchTouchEventable = dispatchTouchEventable;
    }

接下來是分發點選事件。

    /*重寫dispatchTouchEvent*/
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if(ev.getAction() == MotionEvent.ACTION_UP){
            /*獲取當前點選位置,遍歷佈局,獲取當前點選位置對應的view,根據view對映路徑,與json檔案中的對比*/
            int x = (int) ev.getRawX();
            int y = (int) ev.getRawY();

            /*json串中根據Activity值只獲取當前Activity的埋點View*/
            for(int id:ids){
                View view = findViewById(id);
                if(view == null) continue;
                view.getGlobalVisibleRect(rect);
                if(rect.contains(x ,y )){
                    Log.v("out" , "埋點id:"+id);
                    return super.dispatchTouchEvent(ev);
                }
            }
            /*如果執行到這了,說明上面的遍歷沒有找到,那麼當前的view是在fragment中*/
            dispatchTouchEventable.point(x , y);

        }
        return super.dispatchTouchEvent(ev);
    }

這裡寫圖片描述

接下來是Fragment中的寫法:

    @Override
    public View onCreateView(LayoutInflater layoutInflater , ViewGroup viewGroup , Bundle savedInstance){
        super.onCreateView(layoutInflater , viewGroup , savedInstance);
        view = layoutInflater.from(getActivity()).inflate(R.layout.fragment_a , null);
        ids.add(R.id.fragment_a_tv_login);
        ids.add(R.id.fragment_a_tv_register);
        ((BaseActivity)getActivity()).setDispatchTouchEventable(new DispatchTouchEventable() {
            @Override
            public void point(int x, int y) {
                for(int id:ids){
                    View currentview = view.findViewById(id);
                    if(currentview == null) continue;
                    currentview.getGlobalVisibleRect(rect);
                    if(rect.contains(x ,y )){
                        Log.v("out" , "埋點id:"+id);
                    }
                }
            }
        });
        return view;
    }

總結:基本實現了無埋點技術,在實際生產環境中無須在程式碼中手動埋點,只需繼承該基類,伺服器端配置好埋點列表即可。實際應用中應該考慮埋點資料的格式,避免每點選一次都要遍歷所有的id,同時,彈出框,RecyclerView,ListView等的Item點選還不能實現。這些地方需要埋點的可能性較小,如果確實需要,可以程式碼埋點輔助。