五. SDK拓展采集能力
5.0.1 怎样获取TextView
的显示文本?
((TextView) view).getText().toString();
5.0.2 怎样获取ImageView
的显示文本信息?
view.getContentDescription().toString();
5.0.3 怎样采集CheckBox
的点击事件?
5.0.3.1 自定义WrapperOnCheckedChangeListener并且 织入埋点代码
public class WrapperOnCheckedChangeListener implements CompoundButton.OnCheckedChangeListener { private CompoundButton.OnCheckedChangeListener source; public WrapperOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener source) { this.source = source; } @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { //调用原有的 OnClickListener try { if (source != null) { source.onCheckedChanged(compoundButton, b); } } catch (Exception e) { e.printStackTrace(); } //插入埋点代码 SensorsDataPrivate.trackViewOnClick(compoundButton); } }
5.0.3.2 获取 CheckBox 设置的 OnCheckedChangeListener
/** * CheckBox 代理事件 * * @param view compoundButton代理ui */ public void compoundButtonItemClick(View view) { if (view instanceof CheckBox){ final CompoundButton.OnCheckedChangeListener onCheckedChangeListener = SensorsDataHelper.getOnCheckedChangeListener(view); if (onCheckedChangeListener != null && !(onCheckedChangeListener instanceof MkOnCheckedChangeListener)) { ((CompoundButton) view).setOnCheckedChangeListener( new MkOnCheckedChangeListener(onCheckedChangeListener)); } } }
5.0.4 怎样采集RadioGroup
的点击事件?
- 5.0.4.1 确定
RadioGroup
设置的Listener
类型OnGroupClickListener
,然后自定义MkOnGroupClickListener
public class MkOnGroupClickListener implements ExpandableListView.OnGroupClickListener { private ExpandableListView.OnGroupClickListener source; public MkOnGroupClickListener(ExpandableListView.OnGroupClickListener source) { this.source = source; } @Override public boolean onGroupClick(ExpandableListView expandableListView, View view, int groupPosition, long id) { SensorsDataManager.trackAdapterView(expandableListView, view, groupPosition, -1); if (source != null) { source.onGroupClick(expandableListView, view, groupPosition, id); } return false; } }
- 5.0.4.2 判断当前
View
是RadioGroup
if (view instanceof RadioGroup) { try { RadioGroup radioGroup = (RadioGroup) view; Activity activity = SensorsDataHelper.getActivityFromView(view); if (activity != null) { int checkedRadioButtonId = radioGroup.getCheckedRadioButtonId(); RadioButton radioButton = activity.findViewById(checkedRadioButtonId); if (radioButton != null) { text = radioButton.getText().toString(); } } } catch (Exception e) { Log.getStackTraceString(e); } }
- 5.0.4.3如果反射已经设置了
mOnClickListener
,且mOnClickListener
不为空,比去不是我们自定义的MkOnGroupClickListener
- 通过
MkOnGroupClickListener
代理
if (onGroupClickListener != null && !(onGroupClickListener instanceof MkOnGroupClickListener)) { ((ExpandableListView) view).setOnGroupClickListener(new MkOnGroupClickListener(onGroupClickListener)); }
5.0.5 怎样采集RattingBar
的点击事件?
5.0.6 怎样采集 SeekBar
的点击事件?
public void seekBarItemClick(View view) { final SeekBar.OnSeekBarChangeListener onSeekBarChangeListener = SensorsDataHelper.getOnSeekBarChangeListener(view); if (onSeekBarChangeListener != null && !(onSeekBarChangeListener instanceof MkOnSeekBarChangeListener)) { ((SeekBar) view).setOnSeekBarChangeListener( new MkOnSeekBarChangeListener(onSeekBarChangeListener)); } }
5.0.7 怎样采集 Spinner
的点击事件?
5.0.8 怎样采集 ListView
,GridView
的点击事件?
ListView
,GridView
是AdapterView
子类,设置代理逻辑判断都大同小异
- 5.0.8.1 设置
ListView/ GridView
的代理MkAdapterViewOnItemClick
/** * 列表代理事件 * * @param view gridView代理ui */ public void gridViewItemClick(View view) { if (view instanceof ListView || view instanceof GridView){ AdapterView.OnItemClickListener onItemClickListener = ((AdapterView) view).getOnItemClickListener(); if (onItemClickListener != null && !(onItemClickListener instanceof MkAdapterViewOnItemClick)) { ((AdapterView) view).setOnItemClickListener(new MkAdapterViewOnItemClick(onItemClickListener)); } } }
- 5.0.8.1 自定义
MkAdapterViewOnItemClick
源码如下:
public class MkAdapterViewOnItemClick implements AdapterView.OnItemClickListener { private AdapterView.OnItemClickListener source; public MkAdapterViewOnItemClick(AdapterView.OnItemClickListener source) { this.source = source; } @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { if (source != null) { source.onItemClick(adapterView, view, position, id); } SensorsDataManager.trackAdapterView(adapterView, view, position); } }
5.0.9 怎样采集 ExpandableListView
的点击事件?
ExpandableListView
是AdapterView
的子类,同时也是ListView
的子类,ListView
的点击事件分为GroupClick
和ChildClick
,它设置的监听器也有两种,这里我们就需要增加额外的方式去做处理啦,我们来看看 ExpandableListView
的点击事件是如何处理的吧
public static void trackAdapterView(AdapterView<?> adapterView, View view, int groupPosition, int childPosition) { try { final JSONObject jsonObject = new JSONObject(); jsonObject.put(ITrackClickEvent.CANONICAL_NAME, adapterView.getClass().getCanonicalName()); jsonObject.put(ITrackClickEvent.ELEMENT_ID, SensorsDataHelper.getViewId(adapterView)); if (childPosition > -1) { jsonObject.put(ITrackClickEvent.ELEMENT_POSITION, String.format(Locale.CHINA, "%d:%d", groupPosition, childPosition)); } else { jsonObject.put(ITrackClickEvent.ELEMENT_POSITION, String.format(Locale.CHINA, "%d", groupPosition)); } StringBuilder stringBuilder = new StringBuilder(); String viewText = SensorsDataHelper.traverseViewContent(stringBuilder, view); if (!TextUtils.isEmpty(viewText)) { jsonObject.put(ITrackClickEvent.ELEMENT_ELEMENT, viewText); } final Activity activity = SensorsDataHelper.getActivityFromView(adapterView); if (activity != null) { jsonObject.put(ITrackClickEvent.ACTIVITY_NAME, activity.getClass().getCanonicalName()); } SensorsReporter.getSensorsDataApiInstance().track(ITrackClickEvent.APP_CLICK, jsonObject); } catch (Exception e) { Log.getStackTraceString(e); } }
那么我们是如何获取ExpandableListView
的呢?这里主要体现在 $element_position
这个参数上,我们需要根据是group
或者child
做不同的逻辑处理
/** * ExpandableListView代理事件 * * @param view ExpandableListView代理view */ public void expandableItemClick(View view) { if (view instanceof ExpandableListView){ try { final Class viewClazz = Class.forName("android.widget.ExpandableListView"); // ---------------------------------------Child--------------------------------------- Field mOnChildClickListenerField = viewClazz.getDeclaredField("mOnChildClickListener"); if (!mOnChildClickListenerField.isAccessible()) { mOnChildClickListenerField.setAccessible(true); } ExpandableListView.OnChildClickListener onChildClickListener = (ExpandableListView.OnChildClickListener) mOnChildClickListenerField.get(view); if (onChildClickListener != null && !(onChildClickListener instanceof MkOnChildClickListener)) { ((ExpandableListView) view).setOnChildClickListener(new MkOnChildClickListener(onChildClickListener)); } // ---------------------------------------Group--------------------------------------- Field mOnGroupClickListenerField = viewClazz.getDeclaredField("mOnGroupClickListener"); if (!mOnGroupClickListenerField.isAccessible()) { mOnGroupClickListenerField.setAccessible(true); } ExpandableListView.OnGroupClickListener onGroupClickListener = (ExpandableListView.OnGroupClickListener) mOnGroupClickListenerField.get(view); if (onGroupClickListener != null && !(onGroupClickListener instanceof MkOnGroupClickListener)) { ((ExpandableListView) view).setOnGroupClickListener(new MkOnGroupClickListener(onGroupClickListener)); } } catch (Exception e) { Log.getStackTraceString(e); } } }
先通过反射获取mOnGroupClickListener
对象和mOnChildClickListener
,如果listener
不为空,并且不是我们需要的Listener
类型,那么分别通过自定义的的MkOnGroupClickListener
和MkOnChildClickListener
区代理完成。
5.0.9.1 OnGroupClickListene
源码如下:
/** * @author 杨正友(小木箱)于 2020/10/4 15 22 创建 * @Email: yzy569015640@gmail.com * @Tel: 18390833563 * @function description: */ public class MkOnGroupClickListener implements ExpandableListView.OnGroupClickListener { private ExpandableListView.OnGroupClickListener source; public MkOnGroupClickListener(ExpandableListView.OnGroupClickListener source) { this.source = source; } @Override public boolean onGroupClick(ExpandableListView expandableListView, View view, int groupPosition, long id) { SensorsDataManager.trackAdapterView(expandableListView, view, groupPosition, -1); if (source != null) { source.onGroupClick(expandableListView, view, groupPosition, id); } return false; } }
在其onGroupClick
方法内部,我们首先调用埋点代码,然后调用原有的listener
的OnGroupClickListener
方法,这样即可实现插入
埋点代码的效果
5.0.9.2 OnChildClickClickListener
源码如下:
/** * @author 杨正友(小木箱)于 2020/10/4 15 21 创建 * @Email: yzy569015640@gmail.com * @Tel: 18390833563 * @function description: */ public class MkOnChildClickListener implements ExpandableListView.OnChildClickListener { private ExpandableListView.OnChildClickListener source; public MkOnChildClickListener(ExpandableListView.OnChildClickListener source) { this.source = source; } @Override public boolean onChildClick(ExpandableListView expandableListView, View view, int groupPosition, int childPosition, long id) { SensorsDataManager.trackAdapterView(expandableListView, view, groupPosition, childPosition); if (source != null) { return source.onChildClick(expandableListView, view, groupPosition, childPosition, id); } return false; } }
5.1.0 怎样采集 Dialog
的点击事件?
目前这种全埋点的方案是无法采集activity
上游离的view
,如: Dialog
,因为无法遍历到被点击的view
。对于这样的dialog
,我们可以通过如下方式解决
/** * Track Dialog 的点击 * @param activity Activity * @param dialog Dialog */ public void trackDialog(@NonNull final Activity activity, @NonNull final Dialog dialog) { if (dialog.getWindow() != null) { dialog.getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { SensorsDataManager.delegateViewsOnClickListener(activity, dialog.getWindow().getDecorView()); } }); } }
然后在Dialog
show之前调用即可
AlertDialog alertDialog = new AlertDialog.Builder(this) .setNegativeButton("取消", (dialog, which) -> {}) .setPositiveButton("确定", (dialog, which) -> {}) .setTitle("小木箱").setMessage("一定要加油努力哦~").create(); SensorsReporter.getSensorsDataApiInstance().trackDialog(this,alertDialog);