[change]修改调试程序

This commit is contained in:
xinfengkun
2022-06-08 23:01:02 +08:00
parent 24cd8ba0d8
commit f10b4354bd
9 changed files with 401 additions and 169 deletions

View File

@@ -32,6 +32,7 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application
android:name=".App"
android:allowBackup="true"
android:icon="@drawable/icon"
android:label="@string/app_name"

View File

@@ -0,0 +1,13 @@
package com.zhidao.adas.client;
import android.app.Application;
import com.zhidao.adas.client.utils.CrashHandler;
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
CrashHandler.getInstance().init(this);
}
}

View File

@@ -1,5 +1,7 @@
package com.zhidao.adas.client;
import android.util.Pair;
import com.zhidao.adas.client.bean.ArrivalNotification;
import com.zhidao.adas.client.bean.AutopilotState;
import com.zhidao.adas.client.bean.BaseInfo;
@@ -19,6 +21,7 @@ import com.zhidao.adas.client.bean.Trajectory;
import com.zhidao.adas.client.bean.VehicleState;
import com.zhidao.adas.client.bean.Warn;
import com.zhidao.adas.client.log.LogSave;
import com.zhidao.adas.client.utils.Constants;
import com.zhidao.support.adas.high.common.ThreadPoolManager;
import java.text.SimpleDateFormat;
@@ -38,8 +41,7 @@ public class DataDistribution {
private final LinkedBlockingQueue<BaseInfo> queue;
private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS ", Locale.getDefault());
private Future future;
// private final List<OnAdasClientListener> listeners = new ArrayList<>();
private OnAdasClientListener listener;
private Pair<String, OnAdasClientListener> listener;
private volatile boolean isCutDown = true;//是否缩短日志显示
private DataDistribution() {
@@ -58,17 +60,16 @@ public class DataDistribution {
return INSTANCE;
}
public void registerOnAdasClientListener(OnAdasClientListener listener) {
this.listener = null;
public void registerAdasClientListener(Pair<String, OnAdasClientListener> listener) {
this.listener = listener;
// if (!listeners.contains(listener)) {
// listeners.add(listener);
// }
}
// public void unregisterOnAdasClientListener(OnAdasClientListener listener) {
// listeners.remove(listener);
// }
public void unregisterAdasClientListener(Pair<String, OnAdasClientListener> listener) {
if (this.listener != null && listener != null)
if (listener.second.hashCode() == this.listener.second.hashCode()) {
this.listener = null;
}
}
public void addData(BaseInfo info) {
@@ -103,7 +104,6 @@ public class DataDistribution {
public final List<String> listMogoReportMessage = new ArrayList<>();
public final List<String> listPerceptionTrafficLight = new ArrayList<>();
public final List<String> listPredictionObstacleTrajectory = new ArrayList<>();
public final List<String> listBasicInfoReq = new ArrayList<>();
public final List<String> listRecordPanel = new ArrayList<>();
public final List<String> listGlobalPathResp = new ArrayList<>();
public final List<String> listWarn = new ArrayList<>();
@@ -127,220 +127,128 @@ public class DataDistribution {
if (listTrajectory.size() > LIST_SIZE) {
listTrajectory.remove(listTrajectory.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_TRAJECTORY.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof TrackedObjects) {
listTrackedObjects.add(0, time + str);
if (listTrackedObjects.size() > LIST_SIZE) {
listTrackedObjects.remove(listTrackedObjects.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_TRACKED_OBJECTS.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof MyPointCloud) {
listPointCloud.add(0, time + str);
if (listPointCloud.size() > LIST_SIZE) {
listPointCloud.remove(listPointCloud.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_POINT_CLOUD.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof PlanningObjects) {
listPlanningObjects.add(0, time + str);
if (listPlanningObjects.size() > LIST_SIZE) {
listPlanningObjects.remove(listPlanningObjects.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_PLANNING_OBJECTS.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof GnssInfo) {
listGnssInfo.add(0, time + str);
if (listGnssInfo.size() > LIST_SIZE) {
listGnssInfo.remove(listGnssInfo.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_GNSS_INFO.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof VehicleState) {
listVehicleState.add(0, time + str);
if (listVehicleState.size() > LIST_SIZE) {
listVehicleState.remove(listVehicleState.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_VEHICLE_STATE.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof AutopilotState) {
listAutopilotState.add(0, time + str);
if (listAutopilotState.size() > LIST_SIZE) {
listAutopilotState.remove(listAutopilotState.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_AUTOPILOT_STATE.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof MogoReportMessage) {
listMogoReportMessage.add(0, time + str);
if (listMogoReportMessage.size() > LIST_SIZE) {
listMogoReportMessage.remove(listMogoReportMessage.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_REPORT_MESSAGE.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof PerceptionTrafficLight) {
listPerceptionTrafficLight.add(0, time + str);
if (listPerceptionTrafficLight.size() > LIST_SIZE) {
listPerceptionTrafficLight.remove(listPerceptionTrafficLight.size() - 1);
}
if (listener != null) {
listener.onPerceptionTrafficLight((PerceptionTrafficLight) data);
if (listener != null && Constants.TITLE.RECEIVE_PERCEPTION_TRAFFIC_LIGHT.equals(listener.first)) {
listener.second.onPerceptionTrafficLight((PerceptionTrafficLight) data);
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onPerceptionTrafficLight((PerceptionTrafficLight) data);
// }
// }
} else if (data instanceof PredictionObstacleTrajectory) {
listPredictionObstacleTrajectory.add(0, time + str);
if (listPredictionObstacleTrajectory.size() > LIST_SIZE) {
listPredictionObstacleTrajectory.remove(listPredictionObstacleTrajectory.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_PREDICTION_OBSTACLE_TRAJECTORY.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof BasicInfoReq) {
listBasicInfoReq.add(0, time + str);
if (listBasicInfoReq.size() > LIST_SIZE) {
listBasicInfoReq.remove(listBasicInfoReq.size() - 1);
}
if (listener != null) {
listener.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof CarConfigResp) {
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.TITLE_CAR_CONFIG_RESP.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof RecordPanel) {
listRecordPanel.add(0, time + str);
if (listRecordPanel.size() > LIST_SIZE) {
listRecordPanel.remove(listRecordPanel.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_RECORD_RESULT.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof GlobalPathResp) {
listGlobalPathResp.add(0, time + str);
if (listGlobalPathResp.size() > LIST_SIZE) {
listGlobalPathResp.remove(listGlobalPathResp.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_GLOBAL_PATH_RESP.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof Warn) {
listWarn.add(0, time + str);
if (listWarn.size() > LIST_SIZE) {
listWarn.remove(listWarn.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_WARN.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof ArrivalNotification) {
listArrivalNotification.add(0, time + str);
if (listArrivalNotification.size() > LIST_SIZE) {
listArrivalNotification.remove(listArrivalNotification.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_ARRIVAL_NOTIFICATION.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
} else if (data instanceof ErrorData) {
listErrorData.add(0, time + str);
if (listErrorData.size() > 100) {
listErrorData.remove(listErrorData.size() - 1);
}
if (listener != null) {
listener.onRefresh();
if (listener != null && Constants.TITLE.RECEIVE_ERROR.equals(listener.first)) {
listener.second.onRefresh();
}
// if (!listeners.isEmpty()) {
// for (OnAdasClientListener listener : listeners) {
// listener.onRefresh();
// }
// }
}
return temp;
}

View File

@@ -3,6 +3,7 @@ package com.zhidao.adas.client.base;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Pair;
import android.view.View;
import androidx.annotation.NonNull;
@@ -42,17 +43,25 @@ public abstract class BaseFragment extends Fragment {
initHandler();
}
@Override
public void onResume() {
super.onResume();
DataDistribution.getInstance().registerOnAdasClientListener(adasClientListener);
if (!isHidden())
DataDistribution.getInstance().registerAdasClientListener(new Pair<>(title, adasClientListener));
}
@Override
public void onPause() {
super.onPause();
// DataDistribution.getInstance().unregisterOnAdasClientListener(adasClientListener);
DataDistribution.getInstance().unregisterAdasClientListener(new Pair<>(title, adasClientListener));
}
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
DataDistribution.getInstance().registerAdasClientListener(new Pair<>(title, adasClientListener));
}
}
@@ -185,7 +194,8 @@ public abstract class BaseFragment extends Fragment {
protected void handleMessage(Message msg) {
switch (msg.what) {
case WHAT_REFRESH:
onRefreshView();
if (isVisible())
onRefreshView();
break;
}
}

View File

@@ -4,6 +4,7 @@ import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Message;
import android.util.Pair;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
@@ -20,17 +21,16 @@ import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.zhidao.adas.client.DataDistribution;
import com.zhidao.adas.client.OnAdasClientListener;
import com.zhidao.adas.client.R;
import com.zhidao.adas.client.adapter.AutopilotConfigAdapter;
import com.zhidao.adas.client.base.BaseActivity;
import com.zhidao.adas.client.bean.UpdateDataEvent;
import com.zhidao.adas.client.bean.AutoPilotMode;
import com.zhidao.adas.client.DataDistribution;
import com.zhidao.adas.client.bean.UpdateDataEvent;
import com.zhidao.adas.client.utils.Constants;
import com.zhidao.support.adas.high.common.ThreadPoolManager;
import org.greenrobot.eventbus.EventBus;
import java.util.List;
@@ -38,6 +38,7 @@ import java.util.List;
public class AutopilotConfigActivity extends BaseActivity {
private static final String TAG = "CreateActivity";
private Pair<String, OnAdasClientListener> listenerPair;
private TextView toolbar_title;
private RecyclerView recyclerView;
private AutopilotConfigAdapter autopilotConfigAdapter;
@@ -66,6 +67,7 @@ public class AutopilotConfigActivity extends BaseActivity {
getSupportActionBar().setHomeButtonEnabled(true); //设置返回键可用
initHandler();
initRecyclerView();
listenerPair = new Pair<>(Constants.TITLE.RECEIVE_GNSS_INFO, listener);
toolbar_title.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
@@ -80,6 +82,15 @@ public class AutopilotConfigActivity extends BaseActivity {
protected void onResume() {
super.onResume();
init();
DataDistribution.getInstance().registerAdasClientListener(new Pair<>(Constants.TITLE.RECEIVE_GNSS_INFO, listener));
}
@Override
protected void onPause() {
super.onPause();
DataDistribution.getInstance().unregisterAdasClientListener(new Pair<>(Constants.TITLE.RECEIVE_GNSS_INFO, listener));
}
private void init() {
@@ -148,17 +159,6 @@ public class AutopilotConfigActivity extends BaseActivity {
ThreadPoolManager.getsInstance().execute(runnable);
}
@Override
protected void onStart() {
super.onStart();
DataDistribution.getInstance().registerOnAdasClientListener(listener);
}
@Override
protected void onStop() {
super.onStop();
// DataDistribution.getInstance().unregisterOnAdasClientListener(listener);
}
@Override
protected void onDestroy() {

View File

@@ -32,6 +32,7 @@ import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.AppCompatButton;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.GridLayoutManager;
@@ -134,7 +135,7 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas
private final List<String> titleBtnData = new ArrayList<>();
private final List<IPCConnectState> connectStatusList = new ArrayList<>();
private InfoTitleAdapter fragmentAdapter;
private final Map<String, BaseFragment> fragmentList = new HashMap<>();
private Fragment fromFragment;
private FragmentManager manager;
private String ftpTime;
private boolean isPad;
@@ -508,18 +509,18 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas
titleFragmentData.add(Constants.TITLE.RECEIVE_GNSS_INFO);
titleFragmentData.add(Constants.TITLE.RECEIVE_TRAJECTORY);
titleFragmentData.add(Constants.TITLE.RECEIVE_TRACKED_OBJECTS);
titleFragmentData.add(Constants.TITLE.RECEIVE_POINT_CLOUD);
titleFragmentData.add(Constants.TITLE.RECEIVE_PLANNING_OBJECTS);
titleFragmentData.add(Constants.TITLE.RECEIVE_VEHICLE_STATE);
titleFragmentData.add(Constants.TITLE.RECEIVE_AUTOPILOT_STATE);
titleFragmentData.add(Constants.TITLE.RECEIVE_REPORT_MESSAGE);
titleFragmentData.add(Constants.TITLE.RECEIVE_PERCEPTION_TRAFFIC_LIGHT);
titleFragmentData.add(Constants.TITLE.RECEIVE_PREDICTION_OBSTACLE_TRAJECTORY);
titleFragmentData.add(Constants.TITLE.RECEIVE_POINT_CLOUD);
titleFragmentData.add(Constants.TITLE.RECEIVE_PLANNING_OBJECTS);
titleFragmentData.add(Constants.TITLE.RECEIVE_CAR_CONFIG_RESP);
titleFragmentData.add(Constants.TITLE.RECEIVE_RECORD_RESULT);
titleFragmentData.add(Constants.TITLE.RECEIVE_GLOBAL_PATH_RESP);
titleFragmentData.add(Constants.TITLE.RECEIVE_WARN);
titleFragmentData.add(Constants.TITLE.RECEIVE_ARRIVAL_NOTIFICATION);
titleFragmentData.add(Constants.TITLE.RECEIVE_WARN);
titleFragmentData.add(Constants.TITLE.RECEIVE_ERROR);
@@ -959,21 +960,27 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas
}
private void showFragment(String title) {
BaseFragment fragment = fragmentList.get(title);
if (fragment == null) {
Fragment to = manager.findFragmentByTag(title);
if (to == null) {
if (Constants.TITLE.RECEIVE_CAR_CONFIG_RESP.equals(title)) {
AdasManager.getInstance().sendCarConfigReq();
fragment = new VersionFragment("工控机版本\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t固定IP配置");
to = new VersionFragment(Constants.TITLE.TITLE_CAR_CONFIG_RESP);
} else {
fragment = new InfoFragment(title);
to = new InfoFragment(title);
}
fragmentList.put(title, fragment);
}
if (!fragment.isVisible()) {
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.fl_info, fragment);
transaction.commit();
FragmentTransaction transaction = manager.beginTransaction();
if (fromFragment != null) {
transaction.hide(fromFragment);
}
if (!to.isAdded()) {
transaction.add(R.id.fl_info, to, title).commit();
} else {
transaction.show(to).commit();
}
if (Constants.TITLE.RECEIVE_CAR_CONFIG_RESP.equals(title)) {
AdasManager.getInstance().sendCarConfigReq();
}
fromFragment = to;
}
@Override

View File

@@ -25,6 +25,7 @@ import com.zhidao.adas.client.base.BaseFragment;
import com.zhidao.adas.client.bean.Config;
import com.zhidao.support.adas.high.AdasManager;
import com.zhidao.support.adas.high.bean.VersionCompatibility;
import com.zhidao.support.adas.high.common.Constants;
import com.zhidao.support.adas.high.common.CupidLogUtils;
import java.text.SimpleDateFormat;
@@ -163,7 +164,7 @@ public class VersionFragment extends BaseFragment {
temp = ip + ":" + AdasManager.getInstance().getIpcConnectedPort();
}
MessagePad.CarConfigResp adasConfig = AdasManager.getInstance().getCarConfig();
list.add(new Config("更新时间:", sdf.format(new Date())));
list.add(new Config("更新时间:", AdasManager.getInstance().getIpcConnectionStatus() == Constants.IPC_CONNECTION_STATUS.CONNECTED ? sdf.format(new Date()) : null));
list.add(new Config("工控机IP:", temp));
list.add(new Config("工控机版本:", adasConfig == null ? null : adasConfig.getDockVersion()));
list.add(new Config("车牌号:", adasConfig == null ? null : adasConfig.getPlateNumber()));

View File

@@ -155,6 +155,7 @@ public class Constants {
String RECEIVE_PLANNING_OBJECTS = "Planning障碍物";
// String RECEIVE_BASIC_INFO_REQ = "自动驾驶设备基础信息请求";
String TITLE_CAR_CONFIG_RESP = "工控机版本\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t固定IP配置";
String RECEIVE_CAR_CONFIG_RESP = "信息与配置";
String RECEIVE_RECORD_RESULT = "数据采集结果";
String RECEIVE_GLOBAL_PATH_RESP = "自动驾驶路径";

View File

@@ -0,0 +1,291 @@
package com.zhidao.adas.client.utils;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* ClassName: CrashHandler
* Function: UncaughtException处理类,当程序发生Uncaught异常的时候,由该类来接管程序,并记录发送错误报告.
*
* @author Norris Norris.sly@gmail.com
* @Date 2013 2013-3-24 下午12:27:10
* @Fields ──────────────────────────────────────────────────────────────────────────────────────────────────────
* @Methods ──────────────────────────────────────────────────────────────────────────────────────────────────────
* 2013-3-24下午12:27:10 Modified By Norris
* ──────────────────────────────────────────────────────────────────────────────────────────────────────
* @see ──────────────────────────────────────────────────────────────────────────────────────────────────────
* @since Ver 1.0 I used to be a programmer like you, then I took an arrow in the knee
*/
public class CrashHandler implements UncaughtExceptionHandler {
private static final String FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "IPCMonitoring" + File.separator + "Crash" + File.separator;//程序外部存储跟目录
/**
* Log日志的tag
* String : TAG
*
* @since 2013-3-21下午8:44:28
*/
private static final String TAG = "NorrisInfo";
/**
* 系统默认的UncaughtException处理类
* Thread.UncaughtExceptionHandler : mDefaultHandler
*
* @since 2013-3-21下午8:44:43
*/
private UncaughtExceptionHandler mDefaultHandler;
/**
* CrashHandler实例
* CrashHandler : mInstance
*
* @since 2013-3-21下午8:44:53
*/
private static CrashHandler mInstance = new CrashHandler();
/**
* 程序的Context对象
* Context : mContext
*
* @since 2013-3-21下午8:45:02
*/
private Context mContext;
/**
* 用来存储设备信息和异常信息
* Map<String,String> : mLogInfo
*
* @since 2013-3-21下午8:46:15
*/
private final Map<String, String> mLogInfo = new HashMap<String, String>();
/**
* 用于格式化日期,作为日志文件名的一部分(FIXME 注意在windows下文件名无法使用等符号)
* SimpleDateFormat : mSimpleDateFormat
*
* @since 2013-3-21下午8:46:39
*/
private SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyyMMdd_HH-mm-ss");
/**
* Creates a new instance of CrashHandler.
*/
private CrashHandler() {
}
/**
* getInstance:{获取CrashHandler实例 ,单例模式 }
* ──────────────────────────────────
*
* @return CrashHandler
* @throws
* @since I used to be a programmer like you, then I took an arrow in the knee Ver 1.0
* ──────────────────────────────────────────────────────────────────────────────────────────────────────
* 2013-3-21下午8:52:24 Modified By Norris
* ──────────────────────────────────────────────────────────────────────────────────────────────────────
*/
public static CrashHandler getInstance() {
return mInstance;
}
/**
* init:{初始化}
* ──────────────────────────────────
*
* @param paramContext
* @return void
* @throws
* @since I used to be a programmer like you, then I took an arrow in the knee Ver 1.0
* ──────────────────────────────────────────────────────────────────────────────────────────────────────
* 2013-3-21下午8:52:45 Modified By Norris
* ──────────────────────────────────────────────────────────────────────────────────────────────────────
*/
public void init(Context paramContext) {
mContext = paramContext;
// 获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// 设置该CrashHandler为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this);
}
/**
* 当UncaughtException发生时会转入该重写的方法来处理
* (non-Javadoc)
*
* @see UncaughtExceptionHandler#uncaughtException(Thread, Throwable)
*/
public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
// 获取设备参数信息
getDeviceInfo(mContext);
// mLogInfo.put("versionName", String.valueOf(BuildConfig.VERSION_CODE));
// mLogInfo.put("versionCode", BuildConfig.VERSION_NAME);
// 保存日志文件
String result = saveCrashLogToFile(paramThrowable);
mDefaultHandler.uncaughtException(paramThread, paramThrowable);
// if (!handleException(paramThrowable) && mDefaultHandler != null) {
// // 如果自定义的没有处理则让系统默认的异常处理器来处理
// mDefaultHandler.uncaughtException(paramThread, paramThrowable);
// } else {
//// try {
//// // 如果处理了让程序继续运行1秒再退出保证文件保存并上传到服务器
//// paramThread.sleep(1000);
//// } catch (InterruptedException e) {
//// e.printStackTrace();
//// }
// // 退出程序
// android.os.Process.killProcess(android.os.Process.myPid());
// System.exit(1);
// }
}
/**
* handleException:{自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.}
* ──────────────────────────────────
*
* @param paramThrowable
* @return true:如果处理了该异常信息;否则返回false.
* @throws
* @since I used to be a programmer like you, then I took an arrow in the knee Ver 1.0
* ──────────────────────────────────────────────────────────────────────────────────────────────────────
* 2013-3-24下午12:28:53 Modified By Norris
* ──────────────────────────────────────────────────────────────────────────────────────────────────────
*/
public boolean handleException(Throwable paramThrowable) {
if (paramThrowable == null)
return false;
new Thread() {
public void run() {
Looper.prepare();
Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出", Toast.LENGTH_SHORT).show();
Looper.loop();
}
}.start();
// 获取设备参数信息
getDeviceInfo(mContext);
// 保存日志文件
String result = saveCrashLogToFile(paramThrowable);
//上传崩溃日志
return true;
}
/**
* getDeviceInfo:{获取设备参数信息}
* ──────────────────────────────────
*
* @param paramContext
* @throws
* @since I used to be a programmer like you, then I took an arrow in the knee Ver 1.0
* ──────────────────────────────────────────────────────────────────────────────────────────────────────
* 2013-3-24下午12:30:02 Modified By Norris
* ──────────────────────────────────────────────────────────────────────────────────────────────────────
*/
public void getDeviceInfo(Context paramContext) {
try {
// 获得包管理器
PackageManager mPackageManager = paramContext.getPackageManager();
// 得到该应用的信息即主Activity
PackageInfo mPackageInfo = mPackageManager.getPackageInfo(
paramContext.getPackageName(), PackageManager.GET_ACTIVITIES);
if (mPackageInfo != null) {
String versionName = mPackageInfo.versionName == null ? "null"
: mPackageInfo.versionName;
String versionCode = mPackageInfo.versionCode + "";
mLogInfo.put("versionName", versionName);
mLogInfo.put("versionCode", versionCode);
}
} catch (NameNotFoundException e) {
e.printStackTrace();
}
// 反射机制
Field[] mFields = Build.class.getDeclaredFields();
// 迭代Build的字段key-value 此处的信息主要是为了在服务器端手机各种版本手机报错的原因
for (Field field : mFields) {
try {
field.setAccessible(true);
mLogInfo.put(field.getName(), Objects.requireNonNull(field.get("")).toString());
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
/**
* saveCrashLogToFile:{将崩溃的Log保存到本地}
* TODO 可拓展将Log上传至指定服务器路径
* ──────────────────────────────────
*
* @param paramThrowable
* @return FileName
* @throws
* @since I used to be a programmer like you, then I took an arrow in the knee Ver 1.0
* ──────────────────────────────────────────────────────────────────────────────────────────────────────
* 2013-3-24下午12:31:01 Modified By Norris
* ──────────────────────────────────────────────────────────────────────────────────────────────────────
*/
private String saveCrashLogToFile(Throwable paramThrowable) {
StringBuffer mStringBuffer = new StringBuffer();
for (Map.Entry<String, String> entry : mLogInfo.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
mStringBuffer.append(key + "=" + value + "\r\n");
}
Writer mWriter = new StringWriter();
PrintWriter mPrintWriter = new PrintWriter(mWriter);
paramThrowable.printStackTrace(mPrintWriter);
paramThrowable.printStackTrace();
Throwable mThrowable = paramThrowable.getCause();
// 迭代栈队列把所有的异常信息写入writer中
while (mThrowable != null) {
mThrowable.printStackTrace(mPrintWriter);
// 换行 每个个异常栈之间换行
mThrowable = mThrowable.getCause();
}
//记得关闭
String mResult = mWriter.toString();
// String mResult = mWriter.toString().replace("\n", "").replace(":", "").replace("/", "").replace("\t", "");
mStringBuffer.append(mResult);
// 保存文件,设置文件名
String mTime = mSimpleDateFormat.format(new Date());
String mFileName = mContext.getPackageName() + "_Exception-" + mTime + ".log";
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
try {
File mDirectory = new File(FILE_PATH);
Log.v(TAG, mDirectory.toString());
if (!mDirectory.exists())
mDirectory.mkdirs();
FileOutputStream mFileOutputStream = new FileOutputStream(mDirectory + File.separator + mFileName);
mFileOutputStream.write(mStringBuffer.toString().getBytes());
mFileOutputStream.close();
return mResult;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return mResult;
}
}