android 埋點統計方案---已廢棄
阿新 • • 發佈:2019-01-08
最近在研究埋點統計,經過認真調研,整理出了我們自己的一套埋點方案,採用統計所有view點選事件的方案。由於網上內容有很多錯誤或不完整,本文將所有相關技術分析和程式碼完整的貼出來方便大家直接用,可以繞開好多彎路。
本文解決一大問題是在有Fragment切換的時候,Fragment中的view與上一個Fragment中的view出現了衝突的問題,即在viewPage中會預先載入好下一個Fragment,造成點選事件統計衝突。view.isShown()用於判斷fragment是否為當前展示的那一個。
BaseActivity中程式碼
//統計埋點
LinkedHashSet<View> views = new LinkedHashSet<View>();
public LinkedHashSet<View> allView = new LinkedHashSet<View>();
int statusBarHeight;
private String mClassName = this.getClass().getSimpleName();
//分發點選事件
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
View view = getCurrentFocus();
if (isHideInput(view, ev)) {
HideSoftInput(view.getWindowToken());
}
}else if(ev.getAction() == MotionEvent.ACTION_UP){
/*獲取當前點選位置,遍歷佈局,獲取當前點選位置對應的view,根據view對映路徑,與json檔案中的對比*/
eventInViewCollect( ev);
}
return super.dispatchTouchEvent(ev);
}
@Override
public void onWindowFocusChanged (boolean hasFocus){
super.onWindowFocusChanged(hasFocus);
if(!hasFocus) return; //失去焦點時 不執行
collectView();//收集統計用點選view的資訊
}
public void eventInViewCollect(MotionEvent event) {
if (!HengChangAgent.isCollectMode()) return; //非收集模式 退出
double x = event.getRawX();
double y = event.getRawY() - statusBarHeight;
List touchViewid = new ArrayList<String> ();
for(View view :allView) {
Rect outRect = new Rect();
view.getGlobalVisibleRect(outRect);
if(outRect.contains((int)x ,(int)y )){
String idName = ViewUtils.getResourceName(this,view.getId());
// view.isShown() view在上層才獲取其id 針對多個fragment切換情況
if(!TextUtils.isEmpty(idName) && view.isShown()){
touchViewid.add(idName);
}
if (touchViewid.size()>0){
LogUtils.d("HengChangAgent" , "這是我們的埋點:"+touchViewid.toString());
String json= "";
try {
JSONObject jsonObj = new JSONObject();//物件,json形式
jsonObj.put("idName", touchViewid.toString());//向物件裡面新增值
json = jsonObj.toString();
}
catch (Exception e)
{
LogUtils.d("out" , "埋點json生成失敗");
}
HengChangAgent.requestBuriedPointStatistics(/*AppAccount.getInstance().getUserid()+*/"",json);
}
}
}
}
/**
* 收集統計用點選view的資訊
*/
public void collectView() {
if (!HengChangAgent.isCollectMode()) return; //非收集模式 退出
ViewGroup rootView = ViewUtils.getRootFrame(this);
allView = getView(rootView); //獲取到
//過濾掉沒有定義過id的view
LinkedHashSet<View> tempView = new LinkedHashSet<View>();
for (View view :allView){
String idName = ViewUtils.getResourceName(this,view.getId());
if(!TextUtils.isEmpty(idName)){
tempView.add(view);
}
}
allView = tempView;
LogUtils.d("out" , allView.size()+"");
Rect outRect = new Rect();
this.getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect);
statusBarHeight = outRect.top;
}
/*獲取所有View和沒有子View的ViewGroup*/
public LinkedHashSet<View> getView(ViewGroup viewGroup){
if(viewGroup == null) return null;
int count = viewGroup.getChildCount();
for(int i=0;i<count;i++){
View view = viewGroup.getChildAt(i);
if(!(view instanceof ViewGroup)){
views.add(viewGroup);
views.add(view);
}else if(view instanceof ViewGroup){
getView((ViewGroup)view);
}else{
break;
}
}
return views;
}
BaseFragment中的onActivityCreated()新增如下程式碼
/**
* 收集統計用點選view的資訊
*/
public void collectView() {
if (!HengChangAgent.isCollectMode()) return;//非收集模式 退出
if (getActivity() instanceof BaseActivity ){
ViewGroup rootView = ViewUtils.getRootFrame(getActivity());//獲取根viewGroup
LinkedHashSet<View> views = ((BaseActivity)getActivity()).getView(rootView);
if (views ==null || views.size()==0 ) return;
//過濾掉沒有定義過id的view
LinkedHashSet<View> filterViews = new LinkedHashSet<View>();
for (View view :views){
String idName = ViewUtils.getResourceName(getActivity(),view.getId());
if(!TextUtils.isEmpty(idName) && idName.contains(":id/")){
filterViews.add(view);
}
}
((BaseActivity)getActivity()).allView.addAll(filterViews);
}
}
相關工具類
public class ViewUtils {
//獲取Activity的根view
@NonNull
public static FrameLayout getRootFrame(@NonNull Activity activity) {
View re = activity.findViewById(android.R.id.content);
if (re != null && re instanceof FrameLayout) {
return (FrameLayout) re;
}
ViewGroup viewGroup = (ViewGroup) activity.getWindow().getDecorView();
re = viewGroup.getChildAt(viewGroup.getChildCount() - 1);
if (re != null && re instanceof FrameLayout) {
return (FrameLayout) re;
} else {
re = new FrameLayout(activity);
activity.getActionBar().getHeight();
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT
, ViewGroup.LayoutParams.MATCH_PARENT);
viewGroup.addView(re, lp);
return (FrameLayout) re;
}
}
/**
* 獲取資原始檔名字
* @param resid
* @return
*/
public static String getResourceName(@NonNull Context context , @AnyRes int resid){
String res = "";
if (-1 ==resid ) return res;
try {
res = context.getResources().getResourceName(resid);
} catch (Resources.NotFoundException e) {
// e.printStackTrace();
// LogUtils.d("out", "未獲取到ResourceName ---id="+resid);
}
return res;
}
//獲取Activity的根view
public static ViewGroup getRootView(Activity context)
{
return (ViewGroup)((ViewGroup)context.findViewById(android.R.id.content)).getChildAt(0);
}
}