CrashHandler :
package com.example.petrochina_oil;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.Process;
import android.text.TextUtils;
import android.util.Log;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
* 作用:
* 1.收集錯誤信息
* 2.保存錯誤信息
*/
public class CrashHandler implements Thread.UncaughtExceptionHandler {
private static CrashHandler sInstance = null;
private Thread.UncaughtExceptionHandler mDefaultHandler;
private Context mContext;
// 保存手機信息和異常信息
protected Map<String, String> mMessage = new HashMap<>();
protected _Functions functions = new _Functions();
String path = Environment.getExternalStorageDirectory().getPath() + "/mileCrash/";
public static CrashHandler getInstance() {
if (sInstance == null) {
synchronized (CrashHandler.class) {
sInstance = new CrashHandler();
}
}
return sInstance;
}
private CrashHandler() {
}
/**
* 初始化默認異常捕獲
*
* @param context context
*/
public void init(Context context) {
mContext = context;
// 獲取默認異常處理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// 將此類設爲默認異常處理器
Thread.setDefaultUncaughtExceptionHandler(this);
List<String> log_files = functions.getFilesAllName(path);
Log.d("init", "init");
for (int i = 0; i < log_files.size(); i++) {
postToServer(log_files.get(i));
}
}
@Override
public void uncaughtException(Thread t, Throwable e) {
if (!handleException(e)) {
// 未經過人爲處理,則調用系統默認處理異常,彈出系統強制關閉的對話框
if (mDefaultHandler != null) {
mDefaultHandler.uncaughtException(t, e);
}
} else {
// 已經人爲處理,系統自己退出
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
Process.killProcess(Process.myPid());
System.exit(1);
}
}
/**
* 是否人爲捕獲異常
*
* @param e Throwable
* @return true:已處理 false:未處理
*/
private boolean handleException(Throwable e) {
if (e == null) {// 異常是否爲空
return false;
}
Log.e("CrashHandler", "捕捉到異常");
collectErrorMessages();
saveErrorMessages(e);
return false;
}
/**
* 1.收集錯誤信息
*/
private void collectErrorMessages() {
PackageManager pm = mContext.getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
if (pi != null) {
String versionName = TextUtils.isEmpty(pi.versionName) ? "null" : pi.versionName;
String versionCode = "" + pi.versionCode;
mMessage.put("versionName", versionName);
mMessage.put("versionCode", versionCode);
}
// 通過反射拿到錯誤信息
Field[] fields = Build.class.getFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
field.setAccessible(true);
try {
mMessage.put(field.getName(), field.get(null).toString());
Log.e("collectErrorMessages", "收集異常信息");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
/**
* 保存錯誤信息
*
* @param e Throwable
*/
private void saveErrorMessages(Throwable e) {
Log.e("saveErrorMessages", "保存異常信息");
StringBuffer sb = new StringBuffer();
for (Map.Entry<String, String> entry : mMessage.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key + "=" + value + "\n");
}
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
e.printStackTrace(printWriter);
Throwable cause = e.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.close();
String result = writer.toString();
sb.append(result);
Log.e("saveErrorMessages", "異常信息: " + result);
saveToFile(result);
}
private void postToServer(final String file) {
Log.d("crashPostToServer", "start");
String strUrlPath = "http://119.3.56.22/index.php?m=Api&c=Alert&a=postAlert";
OkHttpClient client = new OkHttpClient();//創建OkHttpClient對象。
FormBody.Builder formBody = new FormBody.Builder();//創建表單請求體
//formBody.add("mid",Config.get("mac"));//傳遞鍵值對參數
formBody.add("code", "1001");//傳遞鍵值對參數
String result = functions.getStrFromFile2("", file);
Log.e("postToServer", "異常信息: " + result);
formBody.add("description", result);//傳遞鍵值對參數
Request request = new Request.Builder()//創建Request 對象。
.url(strUrlPath)
.post(formBody.build())//傳遞請求體
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {//回調的方法執行在子線程。
if (response.code() == 200) {
functions.deleteSingleFile(file);
}
}
}
});
}
private void saveToFile(String result) {
String time = new SimpleDateFormat("yyyy-MM-dd HH_mm_ss", Locale.CHINA).format(new Date());
String fileName = time + ".log";
functions.writeStrToFile2(result, fileName, path, false);
}
}
調用:
CrashHandler.getInstance().init(this);