diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/App.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/App.kt index 85e0baa..30dd657 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/App.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/App.kt @@ -3,6 +3,7 @@ package com.yinuo.safetywatcher.watcher import com.common.commonlib.CommonApplication import com.common.commonlib.db.DBUtils import com.common.commonlib.db.entity.Warning +import com.yinuo.safetywatcher.watcher.utils.CrashHandler import com.yinuo.safetywatcher.watcher.utils.GPIOUtils import com.yinuo.safetywatcher.watcher.utils.PlatformUtils import kotlinx.coroutines.DelicateCoroutinesApi @@ -17,6 +18,7 @@ class App : CommonApplication() { override fun onCreate() { super.onCreate() // LztekUtil.setObject(Lztek.create(this)) + CrashHandler.getInstance().init(this) ipConfig() GPIOUtils.openCamera() tryFixDbData() diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/GasListActivity.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/GasListActivity.kt index a07175c..a2a7df4 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/GasListActivity.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/GasListActivity.kt @@ -2,7 +2,6 @@ package com.yinuo.safetywatcher.watcher.ui import android.view.View import androidx.recyclerview.widget.LinearLayoutManager -import com.common.commonlib.utils.getGasShowName import com.yinuo.safetywatcher.R import com.yinuo.safetywatcher.databinding.ActivitySensorBinding import com.yinuo.safetywatcher.watcher.base.NoOptionsActivity @@ -38,7 +37,7 @@ class GasListActivity : NoOptionsActivity() { val mapData = ChartBridge.getMapData() val list = arrayListOf() mapData?.forEach { (t, u) -> - list.add(t.getGasShowName()) + list.add(t) } mAdapter.setData(list) } diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/adapter/GasListAdapter.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/adapter/GasListAdapter.kt index 712e091..b43a39f 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/adapter/GasListAdapter.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/adapter/GasListAdapter.kt @@ -3,6 +3,7 @@ package com.yinuo.safetywatcher.watcher.ui.adapter import android.content.Intent import android.view.LayoutInflater import android.view.ViewGroup +import com.common.commonlib.utils.getGasShowName import com.yinuo.safetywatcher.databinding.LayoutItemGasBinding import com.yinuo.safetywatcher.watcher.base.BaseRvAdapter import com.yinuo.safetywatcher.watcher.ui.ChartActivity @@ -30,7 +31,7 @@ class GasListAdapter : ChartBridge.setSelectGas(data) context.startActivity(Intent(context, ChartActivity::class.java)) } - binding.gasName.text = data + binding.gasName.text = data.getGasShowName() } } } diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/utils/CrashHandler.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/utils/CrashHandler.java new file mode 100644 index 0000000..25fd7ba --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/utils/CrashHandler.java @@ -0,0 +1,178 @@ +package com.yinuo.safetywatcher.watcher.utils; + +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.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.reflect.Field; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +public class CrashHandler implements Thread.UncaughtExceptionHandler { + private static final String TAG = "CrashHandler"; + private Thread.UncaughtExceptionHandler mDefaultHandler;// 系统默认的UncaughtException处理类 + private static CrashHandler INSTANCE = new CrashHandler();// CrashHandler实例 + private Context mContext;// 程序的Context对象 + private Map info = new HashMap();// 用来存储设备信息和异常信息 + private SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");// 用于格式化日期,作为日志文件名的一部分 + + /** + * 保证只有一个CrashHandler实例 + */ + private CrashHandler() { + } + + /** + * 获取CrashHandler实例 ,单例模式 + */ + public static CrashHandler getInstance() { + return INSTANCE; + } + + /** + * 初始化 + * + * @param context + */ + public void init(Context context) { + mContext = context; + mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 获取系统默认的UncaughtException处理器 + Thread.setDefaultUncaughtExceptionHandler(this);// 设置该CrashHandler为程序的默认处理器 + } + + /** + * 当UncaughtException发生时会转入该重写的方法来处理 + */ + public void uncaughtException(Thread thread, Throwable ex) { + if (!handleException(ex) && mDefaultHandler != null) { + // 如果自定义的没有处理则让系统默认的异常处理器来处理 + mDefaultHandler.uncaughtException(thread, ex); + } else { + try { + Thread.sleep(5000);// 如果处理了,让程序继续运行3秒再退出,保证文件保存并上传到服务器 + } catch (InterruptedException e) { + e.printStackTrace(); + } + // // 退出程序 + // App.exit(mContext); + android.os.Process.killProcess(android.os.Process.myPid()); + System.exit(1); + } + } + + /** + * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. + * + * @param ex 异常信息 + * @return true 如果处理了该异常信息;否则返回false. + */ + public boolean handleException(Throwable ex) { + if (ex == null) + return false; + new Thread() { + public void run() { + Looper.prepare(); + Toast.makeText(mContext, "sorry!!!app出问题了,正在把日志保存到sdcard crash目录下", Toast.LENGTH_SHORT).show(); + Looper.loop(); + } + }.start(); + // 收集设备参数信息 + collectDeviceInfo(mContext); + // 保存日志文件 + saveCrashInfo2File(ex); + Log.w(TAG, ex.getMessage()); + return true; + } + + /** + * 收集设备参数信息 + * + * @param context + */ + public void collectDeviceInfo(Context context) { + try { + PackageManager pm = context.getPackageManager();// 获得包管理器 + //2023 / 12 / 18 09:54 Android异常处理(1)-- + //使用UncaughtExceptionHandler 类捕抓异常信息_12506227的技术博客_51CTO博客 + //https://blog.51cto.com/u_12516227/6055706 2/2 + PackageInfo pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);// 得到该应用的信息,即主Activity + if (pi != null) { + String versionName = pi.versionName == null ? "null" : pi.versionName; + String versionCode = pi.versionCode + ""; + info.put("versionName", versionName); + info.put("versionCode", versionCode); + } + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + Field[] fields = Build.class.getDeclaredFields();// 反射机制 + for (Field field : fields) { + try { + field.setAccessible(true); + info.put(field.getName(), field.get("").toString()); + Log.d(TAG, field.getName() + ":" + field.get("")); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + + private String saveCrashInfo2File(Throwable ex) { + StringBuffer sb = new StringBuffer(); + for (Map.Entry entry : info.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + sb.append(key + "=" + value + "\r\n"); + } + Writer writer = new StringWriter(); + PrintWriter pw = new PrintWriter(writer); + ex.printStackTrace(pw); + Throwable cause = ex.getCause(); + // 循环着把所有的异常信息写入writer中 + while (cause != null) { + cause.printStackTrace(pw); + cause = cause.getCause(); + } + pw.close();// 记得关闭 + String result = writer.toString(); + sb.append(result); + // 保存文件 + //long timetamp = System.currentTimeMillis(); + String time = format.format(new Date()); + String fileName = "crash-" + time + ".log"; + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + try { + File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + + "crash"); + Log.i("CrashHandler", dir.toString()); + if (!dir.exists()) + dir.mkdir(); + FileOutputStream fos = new FileOutputStream(new File(dir, fileName)); + fos.write(sb.toString().getBytes()); + fos.close(); + return fileName; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } +}