Files
MoGoEagleEye/app/src/main/java/com/mogo/launcher/crash/CrashSystem.java
2023-09-22 11:37:06 +08:00

215 lines
7.2 KiB
Java

package com.mogo.launcher.crash;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
import java.io.File;
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.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class CrashSystem implements UncaughtExceptionHandler {
public static final String TAG = "CrashSystem";
private String mAppPackage = null;
private String mAppVersionCode = null;
private String mAppVersionName = null;
private String mAppName = null;
private String mOsVersion = null;
private String mDeviceId = null;
private UncaughtExceptionHandler mDefaultHandler;
private final Map<String, String> info = new HashMap<>();
private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
private boolean mDebug = false;
private final List<CrashCallback> callbackList = new ArrayList<>();
private static CrashSystem sCrashSystem = null;
private static final Object lock = new Object();
public void init() {
this.mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
/**
* 是否收集记录crash信息
* @param debug 是否是debug
*/
public void setDebug(boolean debug) {
this.mDebug = debug;
}
/**
* 添加crash事件回调
*/
public void addCallback(CrashCallback callback) {
if(callback != null) {
callbackList.add(callback);
}
}
private CrashSystem(Context context) {
this.inflateSystemInfo(context);
}
public static CrashSystem getInstance(Context context) {
CrashSystem crashSystem = sCrashSystem;
if(crashSystem == null) {
synchronized (lock) {
crashSystem = sCrashSystem;
if(crashSystem == null) {
crashSystem = new CrashSystem(context.getApplicationContext());
sCrashSystem = crashSystem;
}
}
}
return crashSystem;
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
try {
this.handleException(ex);
dispatchCrashError();
} finally {
if (mDefaultHandler != null) {
mDefaultHandler.uncaughtException(thread, ex);
}
}
}
/**
* 分发异常事件
*/
private void dispatchCrashError() {
for (CrashCallback callback : callbackList) {
if(callback != null) {
callback.onCrashError();
}
}
}
private boolean handleException(Throwable ex) {
if (ex != null) {
String msg = ex.getLocalizedMessage();
Log.e("CrashSystem", msg);
String filePath = saveCrashInfo2File(ex);
Log.i(TAG, "handleException: filePath = " + filePath);
}
return true;
}
private String saveCrashInfo2File(Throwable ex) {
try {
if(!Environment.getExternalStorageState().equals("mounted")) {
return null;
}
File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "crash");
if(!dir.exists()) {
dir.mkdir();
}
String[] fileList = dir.list((dir1, name) -> name.contains(mAppPackage));
if(fileList == null || fileList.length >= 20) { //避免crash日志一直重复
return null;
}
String time = this.format.format(new Date());
String fileName = "app-crash-" + this.mAppPackage + "-" + time + ".log";
if(mDebug) {
fileName = "debug-" + fileName;
}
String fileTemp = fileName + ".temp";
StringBuilder sb = new StringBuilder();
Iterator<Entry<String, String>> var4 = this.info.entrySet().iterator();
String result;
while(var4.hasNext()) {
Entry<String, String> entry = var4.next();
String key = entry.getKey();
result = entry.getValue();
sb.append(key).append("=").append(result).append("\n");
}
sb.append("TIME=").append(System.currentTimeMillis()).append("\n");
sb.append("fileName=").append(fileName).append("\n");
Writer writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
ex.printStackTrace(pw);
for(Throwable cause = ex.getCause(); cause != null; cause = cause.getCause()) {
cause.printStackTrace(pw);
}
pw.close();
result = writer.toString();
sb.append(result);
FileOutputStream fos = null;
try {
File dest = new File(dir, fileTemp);
fos = new FileOutputStream(dest);
fos.write(sb.toString().getBytes());
fos.flush();
File file = new File(dir,fileName);
dest.renameTo(file);
return dir.getAbsolutePath() + File.separator + fileName;
} catch (IOException var13) {
var13.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException ignore) {}
}
} catch (Throwable ignore) {
}
return null;
}
private void inflateSystemInfo(Context context) {
this.mAppPackage = context.getPackageName();
PackageManager pm = context.getPackageManager();
try {
PackageInfo packageInfo = pm.getPackageInfo(this.mAppPackage, 0);
this.mAppVersionCode = String.valueOf(packageInfo.versionCode);
this.mAppVersionName = packageInfo.versionName;
this.mAppPackage = packageInfo.packageName;
this.mAppName = packageInfo.applicationInfo.loadLabel(context.getPackageManager()).toString();
this.mOsVersion = Build.DISPLAY;
String deviceId = MoGoAiCloudClientConfig.getInstance().getSn();
if(TextUtils.isEmpty(deviceId)) {
deviceId = "11111111";
}
this.mDeviceId = deviceId;
} catch (Exception var5) {
var5.printStackTrace();
}
this.info.put("appName",this.mAppName);
this.info.put("appPackageName", this.mAppPackage);
this.info.put("versionCode", this.mAppVersionCode);
this.info.put("versionName", this.mAppVersionName);
this.info.put("sn", this.mDeviceId);
this.info.put("DISPLAY", this.mOsVersion);
}
public interface CrashCallback {
void onCrashError();
}
}