|
@@ -0,0 +1,224 @@
|
|
|
+package com.example.informationkanban.utils;
|
|
|
+
|
|
|
+import android.app.AlarmManager;
|
|
|
+import android.app.Application;
|
|
|
+import android.app.PendingIntent;
|
|
|
+import android.content.Context;
|
|
|
+import android.content.Intent;
|
|
|
+import android.os.Build;
|
|
|
+import android.util.Log;
|
|
|
+
|
|
|
+import com.example.informationkanban.BuildConfig;
|
|
|
+import com.example.informationkanban.common.Constant;
|
|
|
+
|
|
|
+import org.json.JSONObject;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileWriter;
|
|
|
+import java.io.IOException;
|
|
|
+
|
|
|
+import okhttp3.Call;
|
|
|
+import okhttp3.Callback;
|
|
|
+import okhttp3.FormBody;
|
|
|
+import okhttp3.OkHttpClient;
|
|
|
+import okhttp3.Request;
|
|
|
+import okhttp3.Response;
|
|
|
+import xcrash.ICrashCallback;
|
|
|
+import xcrash.TombstoneManager;
|
|
|
+import xcrash.TombstoneParser;
|
|
|
+import xcrash.XCrash;
|
|
|
+
|
|
|
+public class XCrashUtils {
|
|
|
+ private final static String TAG = "XCrashUtils";
|
|
|
+
|
|
|
+ private Application app;
|
|
|
+ private OkHttpClient okHttpClient;
|
|
|
+
|
|
|
+ // callback for java crash, native crash and ANR
|
|
|
+ private final ICrashCallback callback = new ICrashCallback() {
|
|
|
+ @Override
|
|
|
+ public void onCrash(String logPath, String emergency) {
|
|
|
+ Log.d(TAG, "log path: " + (logPath != null ? logPath : "(null)") + ", emergency: " + (emergency != null ? emergency : "(null)"));
|
|
|
+
|
|
|
+ if (emergency != null) {
|
|
|
+ debug(logPath, emergency);
|
|
|
+
|
|
|
+ // Disk is exhausted, send crash report immediately.
|
|
|
+ //sendThenDeleteCrashLog(logPath, emergency);
|
|
|
+ } else {
|
|
|
+ // Add some expanded sections. Send crash report at the next time APP startup.
|
|
|
+
|
|
|
+ // OK
|
|
|
+ TombstoneManager.appendSection(logPath, "expanded_key_1", "expanded_content");
|
|
|
+ TombstoneManager.appendSection(logPath, "expanded_key_2", "expanded_content_row_1\nexpanded_content_row_2");
|
|
|
+
|
|
|
+ // Invalid. (Do NOT include multiple consecutive newline characters ("\n\n") in the content string.)
|
|
|
+ // TombstoneManager.appendSection(logPath, "expanded_key_3", "expanded_content_row_1\n\nexpanded_content_row_2");
|
|
|
+
|
|
|
+ debug(logPath, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Disk is exhausted, send crash report immediately.
|
|
|
+ //sendThenDeleteCrashLog(logPath, emergency);
|
|
|
+
|
|
|
+ //非debug版本上传crash日志
|
|
|
+ if (!BuildConfig.DEBUG) {
|
|
|
+ uploadCrashLog(logPath);
|
|
|
+ } else {
|
|
|
+ AppUtil.reboot(app);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ //ANR Catcher
|
|
|
+ private final ICrashCallback anrCallback = new ICrashCallback() {
|
|
|
+ @Override
|
|
|
+ public void onCrash(String logPath, String emergency) {
|
|
|
+ Log.d(TAG, "log path: " + (logPath != null ? logPath : "(null)") + ", emergency: " + (emergency != null ? emergency : "(null)"));
|
|
|
+
|
|
|
+ if (emergency != null) {
|
|
|
+ debug(logPath, emergency);
|
|
|
+
|
|
|
+ // Disk is exhausted, send crash report immediately.
|
|
|
+ //sendThenDeleteCrashLog(logPath, emergency);
|
|
|
+ } else {
|
|
|
+ // Add some expanded sections. Send crash report at the next time APP startup.
|
|
|
+
|
|
|
+ // OK
|
|
|
+ TombstoneManager.appendSection(logPath, "expanded_key_1", "expanded_content");
|
|
|
+ TombstoneManager.appendSection(logPath, "expanded_key_2", "expanded_content_row_1\nexpanded_content_row_2");
|
|
|
+
|
|
|
+ // Invalid. (Do NOT include multiple consecutive newline characters ("\n\n") in the content string.)
|
|
|
+ // TombstoneManager.appendSection(logPath, "expanded_key_3", "expanded_content_row_1\n\nexpanded_content_row_2");
|
|
|
+
|
|
|
+ debug(logPath, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ AppUtil.reboot(app);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ public void init(Application application) {
|
|
|
+ Log.d(TAG, "xCrash SDK init: start");
|
|
|
+ app = application;
|
|
|
+
|
|
|
+ // Initialize xCrash.
|
|
|
+ XCrash.init(application, new XCrash.InitParameters()
|
|
|
+ .setAppVersion(BuildConfig.VERSION_NAME)
|
|
|
+ .setJavaRethrow(true)
|
|
|
+ .setJavaLogCountMax(10)
|
|
|
+ .setJavaDumpAllThreadsWhiteList(new String[]{"^main$", "^Binder:.*", ".*Finalizer.*"})
|
|
|
+ .setJavaDumpAllThreadsCountMax(10)
|
|
|
+ .setJavaCallback(callback)
|
|
|
+ .setNativeRethrow(true)
|
|
|
+ .setNativeLogCountMax(10)
|
|
|
+ .setNativeDumpAllThreadsWhiteList(new String[]{"^xcrash\\.sample$", "^Signal Catcher$", "^Jit thread pool$", ".*(R|r)ender.*", ".*Chrome.*"})
|
|
|
+ .setNativeDumpAllThreadsCountMax(10)
|
|
|
+ .setNativeCallback(callback)
|
|
|
+ .setAnrRethrow(true)
|
|
|
+ .setAnrLogCountMax(10)
|
|
|
+ .setAnrCallback(anrCallback)
|
|
|
+ .setPlaceholderCountMax(3)
|
|
|
+ .setPlaceholderSizeKb(512)
|
|
|
+ .setLogDir(application.getExternalFilesDir("xcrash").toString())
|
|
|
+ .setLogFileMaintainDelayMs(5000));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void uploadCrashLog(String path) {
|
|
|
+ final File logFile = new File(path);
|
|
|
+ if (logFile.exists()) {
|
|
|
+ String url = NetFunctionConfig.getServerIp() + ":" + Constant.URL_PORT + "/ncs/upload/file";
|
|
|
+ HttpHelper.upload(url, logFile, TAG, new HttpHelper.UploadCallback() {
|
|
|
+ @Override
|
|
|
+ public void onFail() {
|
|
|
+ Log.e(TAG,"错误日志文件上传失败!");
|
|
|
+ AppUtil.reboot(app);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onSuccess(String data) {
|
|
|
+ Log.e(TAG,"错误日志文件上传成功!" + data);
|
|
|
+ sendThenDeleteCrashLog(url + data, null);
|
|
|
+ //删除日志文件
|
|
|
+ //logFile.delete();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void sendThenDeleteCrashLog(final String logPath, String emergency) {
|
|
|
+ try {
|
|
|
+ // Parse
|
|
|
+ //Map<String, String> map = TombstoneParser.parse(logPath, emergency);
|
|
|
+ //String crashReport = new JSONObject(map).toString();
|
|
|
+
|
|
|
+ if(okHttpClient == null){
|
|
|
+ okHttpClient = new OkHttpClient();
|
|
|
+ }
|
|
|
+
|
|
|
+ FormBody.Builder formBody = new FormBody.Builder();
|
|
|
+ formBody.add("class_name", app.getPackageName());
|
|
|
+ formBody.add("method_name", "");
|
|
|
+ formBody.add("exception_name", "");
|
|
|
+ formBody.add("err_msg", "");
|
|
|
+ formBody.add("stack_trace", logPath);
|
|
|
+
|
|
|
+ String url = NetFunctionConfig.getServerIp() + ":" + Constant.URL_PORT;
|
|
|
+ Request request = new Request.Builder()
|
|
|
+ .url(url + "/device/error_log")
|
|
|
+ .post(formBody.build())
|
|
|
+ .build();
|
|
|
+
|
|
|
+ okHttpClient.newCall(request).enqueue(new Callback() {
|
|
|
+ @Override
|
|
|
+ public void onFailure(Call call, IOException e) {
|
|
|
+ Log.e(TAG,"错误日志名称上传失败"+e.getMessage());
|
|
|
+ AppUtil.reboot(app);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onResponse(Call call, Response response) throws IOException {
|
|
|
+ Log.d(TAG,"错误日志名称上传成功");
|
|
|
+ TombstoneManager.deleteTombstone(logPath);
|
|
|
+ //String data = response.body().string();
|
|
|
+ //Log.d(TAG,"错误日志数据 data "+data);
|
|
|
+ AppUtil.reboot(app);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ AppUtil.reboot(app);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Send the crash report to server-side.
|
|
|
+ // ......
|
|
|
+
|
|
|
+ // If the server-side receives successfully, delete the log file.
|
|
|
+ //
|
|
|
+ // Note: When you use the placeholder file feature,
|
|
|
+ // please always use this method to delete tombstone files.
|
|
|
+ //
|
|
|
+ //TombstoneManager.deleteTombstone(logPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void debug(String logPath, String emergency) {
|
|
|
+ // Parse and save the crash info to a JSON file for debugging.
|
|
|
+ FileWriter writer = null;
|
|
|
+ try {
|
|
|
+ File debug = new File(XCrash.getLogDir() + "/debug.json");
|
|
|
+ debug.createNewFile();
|
|
|
+ writer = new FileWriter(debug, false);
|
|
|
+ writer.write(new JSONObject(TombstoneParser.parse(logPath, emergency)).toString());
|
|
|
+ } catch (Exception e) {
|
|
|
+ Log.d(TAG, "debug failed", e);
|
|
|
+ } finally {
|
|
|
+ if (writer != null) {
|
|
|
+ try {
|
|
|
+ writer.close();
|
|
|
+ } catch (Exception ignored) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|