ExceptionMonitor.java
import android.app.Activity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
/**
* 异常监控
* 使用:
* 1.BaseActivity里重写该方法
*
* @Override public boolean dispatchTouchEvent(MotionEvent ev) {
* ExceptionMonitor.getInstance().onDispatchTouchEvent(this, ev);
* return super.dispatchTouchEvent(ev);
* }
* 2.注册Activity生命周期或者在BaseActivity里所有方法:0x001(见末尾)
*/
public class ExceptionMonitor {
private static ExceptionMonitor mExceptionMonitor = null;
private float lastX;
private float lastY;
private ExceptionMonitor() {
}
public static ExceptionMonitor getInstance() {
synchronized (ExceptionMonitor.class) {
if (mExceptionMonitor == null) {
mExceptionMonitor = new ExceptionMonitor();
}
}
return mExceptionMonitor;
}
public void onCreate(Activity activity) {
StepsHelper.enqueueStep(activity, "onCreate");
}
public void onResume(Activity activity) {
StepsHelper.enqueueStep(activity, "onResume");
}
public void onPause(Activity activity) {
StepsHelper.enqueueStep(activity, "onPause");
}
public void onDestroy(Activity activity) {
StepsHelper.enqueueStep(activity, "onDestroy");
}
public void onDispatchTouchEvent(Activity activity, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
this.lastX = event.getRawX();
this.lastY = event.getRawY();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
float currentX = event.getRawX();
float currentY = event.getRawY();
if (lastX == currentX && lastY == currentY) {
// 判断是点击操作
View view = this.getView(activity.getWindow().getDecorView(), currentX, currentY);
// 把view事件记录到队列里边
StepsHelper.enqueueStep(activity, view);
}
}
}
private View getView(View decorView, float currentX, float currentY) {
View targetView = null;
int[] pos = new int[2];
decorView.getLocationInWindow(pos);
if (determinePos(currentX, currentY, pos[0], pos[1], decorView.getWidth(), decorView.getHeight())) {
if (decorView instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) decorView).getChildCount(); ++i) {
View tempView = ((ViewGroup) decorView).getChildAt(i);
// 递归获取目标view
targetView = getView(tempView, currentX, currentY);
if (targetView != null) {
break;
}
}
} else {
targetView = decorView;
}
}
return targetView;
}
// 判断触控点在窗口范围内
private boolean determinePos(float var1, float var2, int var3, int var4, int var5, int var6) {
return var1 >= (float) var3 && var1 <= (float) (var3 + var5) && var2 >= (float) var4 && var2 <= (float) (var4 + var6);
}
}
/*0x001
private class ActivityLifecycle implements Application.ActivityLifecycleCallbacks {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
ActivityManages.getInstance().addActivity(activity);
}
@Override
public void onActivityStarted(Activity activity) {
ExceptionMonitor.getInstance().onCreate(activity);
}
@Override
public void onActivityResumed(Activity activity) {
ExceptionMonitor.getInstance().onResume(activity);
}
@Override
public void onActivityPaused(Activity activity) {
ExceptionMonitor.getInstance().onPause(activity);
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
ActivityManages.getInstance().removeActivty(activity);
ExceptionMonitor.getInstance().onDestroy(activity);
}
}*/
StepsHelper.java
import android.app.Activity;
import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public class StepsHelper {
private static List<String> stepQueue = new ArrayList<>(); //储存用户操作步骤的队列
private static StringBuilder stepBuilder = new StringBuilder();
private float lastX;
private float lastY;
public static void enqueueStep(Context context, String state) {
String time = DateUtil.formatCurrentDate(DateUtil.REGEX_DATE_TIME);
stepBuilder.append(time)
.append(" ")
.append(context.getClass().getName())
.append(" ")
.append(state);
String s = stepBuilder.toString();
stepQueue.add(s);
XLog.commonLog("插桩日志", s);
stepBuilder.delete(0, stepBuilder.length());
}
public static void enqueueStep(Context context, View view) {
if (view == null) {
return;
}
String time = DateUtil.formatCurrentDate(DateUtil.REGEX_DATE_TIME);
String path = view.getResources().getResourceName(view.getId());
String viewId = path.substring(path.indexOf("/") + 1);
stepBuilder.append(time)
.append(" ")
.append(context.getClass().getName())
.append(" Event:viewId:")
.append(viewId)
.append(" Type: ")
.append(view.getClass().getName());
String s = stepBuilder.toString();
stepQueue.add(s);
XLog.commonLog("插桩日志", s);
stepBuilder.delete(0, stepBuilder.length());
}
public void onDispatchTouchEvent(Activity activity, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
this.lastX = event.getRawX();
this.lastY = event.getRawY();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
float currentX = event.getRawX();
float currentY = event.getRawY();
if (lastX == currentX && lastY == currentY) {
// 判断是点击操作
View view = this.getView(activity.getWindow().getDecorView(), currentX, currentY);
// 把view事件记录到队列里边
StepsHelper.enqueueStep(activity, view);
}
}
}
private View getView(View decorView, float currentX, float currentY) {
View targetView = null;
int[] pos = new int[2];
decorView.getLocationInWindow(pos);
if (determinePos(currentX, currentY, pos[0], pos[1], decorView.getWidth(), decorView.getHeight())) {
if (decorView instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) decorView).getChildCount(); ++i) {
View tempView = ((ViewGroup) decorView).getChildAt(i);
// 递归获取目标view
targetView = getView(tempView, currentX, currentY);
if (targetView != null) {
break;
}
}
} else {
targetView = decorView;
}
}
return targetView;
}
// 判断触控点在窗口范围内
private boolean determinePos(float var1, float var2, int var3, int var4, int var5, int var6) {
return var1 >= (float) var3 && var1 <= (float) (var3 + var5) && var2 >= (float) var4 && var2 <= (float) (var4 + var6);
}
public static String flushString() {
String s = stepQueue.toString();
stepQueue.clear();
return s;
}
}