Android收集崩溃日志并上传

el/2024/4/19 23:14:25
public class CrashHandler implements Thread.UncaughtExceptionHandler {public static final String TAG = "CrashHandler";// 系统默认的UncaughtException处理类private Thread.UncaughtExceptionHandler mDefaultHandler;// CrashHandler实例private static CrashHandler INSTANCE = new CrashHandler();// 程序的Context对象private Context mContext;// 用来存储设备信息和异常信息private Map<String, String> infos = new HashMap<String, String>();// 用于格式化日期,作为日志文件名的一部分private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss SSS");private CrashHandler() {}/** 获取CrashHandler实例 ,单例模式 */public static CrashHandler getInstance() {return INSTANCE;}/*** 初始化** @param context*/public void init(Context context) {mContext = context;// 获取系统默认的UncaughtException处理器mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 设置该CrashHandler为程序的默认处理器Thread.setDefaultUncaughtExceptionHandler(this);}/*** 当UncaughtException发生时会转入该函数来处理*/@Overridepublic void uncaughtException(Thread thread, Throwable ex) {if (!handleException(ex) && mDefaultHandler != null) {// 如果用户没有处理则让系统默认的异常处理器来处理mDefaultHandler.uncaughtException(thread, ex);} else {try {Thread.sleep(3000);} catch (InterruptedException e) {Log.e(TAG, "error : ", e);}// 退出程序android.os.Process.killProcess(android.os.Process.myPid());System.exit(1);}}/*** 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.** @param ex* @return true:如果处理了该异常信息;否则返回false.*/private boolean handleException(Throwable ex) {if (ex == null) {return false;}// 使用Toast来显示异常信息new Thread() {@Overridepublic void run() {Looper.prepare();Toast.makeText(mContext, "很抱歉,程序出现异常即将退出.", Toast.LENGTH_LONG).show();Looper.loop();}}.start();Log.e(TAG, "handleException: "+ex.getMessage());// 收集设备参数信息collectDeviceInfo(mContext);// 保存日志文件saveCrashInfo2File(ex);return true;}/*** 收集设备参数信息** @param ctx*/public void collectDeviceInfo(Context ctx) {try {PackageManager pm = ctx.getPackageManager();PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);if (pi != null) {String versionName = pi.versionName == null ? "null" : pi.versionName;String versionCode = pi.versionCode + "";infos.put("versionName", versionName);infos.put("versionCode", versionCode);}} catch (PackageManager.NameNotFoundException e) {Log.e(TAG, "an error occured when collect package info", e);}Field[] fields = Build.class.getDeclaredFields();for (Field field : fields) {try {field.setAccessible(true);infos.put(field.getName(), field.get(null).toString());Log.d(TAG, field.getName() + " : " + field.get(null));} catch (Exception e) {Log.e(TAG, "an error occured when collect crash info", e);}}}/*** 保存错误信息到文件中* 也可以在这里去将错误信息上传给后台的接口* @param ex* @return 返回文件名称,便于将文件传送到服务器*/private String saveCrashInfo2File(Throwable ex) {StringBuffer sb = new StringBuffer();for (Map.Entry<String, String> entry : infos.entrySet()) {String key = entry.getKey();String value = entry.getValue();sb.append(key + "=" + value + "\n");}Writer writer = new StringWriter();PrintWriter printWriter = new PrintWriter(writer);ex.printStackTrace(printWriter);Throwable cause = ex.getCause();while (cause != null) {cause.printStackTrace(printWriter);cause = cause.getCause();}printWriter.close();String result = writer.toString();sb.append(result);try {String time = formatter.format(new Date());String fileName = time + ".txt";if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/CrashCollection/";File dir = new File(path);if (!dir.exists()) {dir.mkdirs();}File file = new File(dir , fileName);if (!file.exists()){file.createNewFile();}FileOutputStream fos = new FileOutputStream(file);fos.write(sb.toString().getBytes("UTF-8"));fos.close();}return fileName;} catch (Exception e) {Log.e(TAG, "an error occured while writing file...", e);}return null;}
}

 

在saveCrashInfo2File(Throwable ex)函数中将错误信息写入了手机内部,当然也可以在这里去进行接口的调用,上传错误信息

在application中需要对该类进行初始化:

CrashHandler crashHandler = CrashHandler.getInstance();

crashHandler.init(this);


http://www.ngui.cc/el/5181717.html

相关文章

Android Text设置神器之SpanableString

TextView在Android中几乎是再常见不过的控件了&#xff0c;几乎遍布在各个角落里&#xff0c;对TextView并没有什么技术点来做分析&#xff0c;但是有时候可能会需要你在项目中处理一些特殊字体&#xff0c;比如下划线&#xff0c;横穿线&#xff0c;亦或者是为TextView部分字体…

Recyclerview内部的bug:IndexOutOfBoundsException: Inconsistency detected

错误日志 java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 15(offset:15).state:25 android.support.v7.widget.RecyclerView{8dfa7c VFE...... ........ 15,15-795,1584 #7f090068 app:id/classics_list}, adapter:com.huishoubao.nqy.a…

Android客户端修改加载的h5页面样式

为什么要修改 有的网页在你设置了WebView的WebSetting的时候,在手机端的显示会比较满意,但是部分网页以及部分手机就算你设置了WebSetting,但是在显示的时候还是会有问题,比如网页顶部的标题字体太大,当显示到手机的时候字体出现了重叠,影响用户体验效果。 如何修改 W…

Transition:Activity过渡、共享元素动画

本文原项目地址为&#xff1a;https://github.com/lgvalle/Material-Animations 在文章最后&#xff0c;有我自己对着这个项目手敲的一份。 代码基本一模一样&#xff0c;只有略微的修改&#xff0c;加了一些注释&#xff0c;以及将其中大多数英文翻译成了中文。 此篇 API 均为…

ModeMVC:在activity中堆代码就叫做MVC吗?

首先&#xff0c;看看这是不是自己 现在Android编程中如果在你没有特别认真设计框架&#xff0c;没有认真考虑面向对象的六大原则对编程重要性的时候&#xff0c;我们一般都是认为自己使用的是MVC的框架模式。但是你使用的真的是MVC吗&#xff1f;还是只是单纯的在activity中堆…

Android饼状图绘制

效果图 代码 https://github.com/269138004/PieChartsView 说明 有时间再补充

Android canvas.save()与canvas.restore()的使用总结

含义 canvas.save(); 画布将当前的状态保存 canvas.restore(); 画布取出原来所保存的状态 使用 canvas.save();与canvas.restore();一般结合使用&#xff0c;.save()函数在前&#xff0c;.restore()函数在后&#xff0c;用来保证在这两个函数之间所做的操作不会对原来在c…

一个小Demo来理解关于IPC(进程间通信)中的aidl

项目地址: Server端代码:Server端代码链接 Client端代码:Client端代码链接 1、IPC的基本要求 IPC(Inter-Process Communication)进程间通信是要在两个相互独立的进程之间进行信息的传递,在Android中每个进程都会被分配一个独立的虚拟机,以及内存空间,还会有自己的App…

AtomicBoolean的介绍与使用

AtomicBoolean是java.util.concurrent.atomic包下的原子变量&#xff0c;这个包里面提供了一组原子类。其基本的特性就是在多线程环境下&#xff0c;当有多个线程同时执行这些类的实例包含的方法时&#xff0c;具有排他性&#xff0c;即当某个线程进入方法&#xff0c;执行其中…

android 手机分辨率与DPI对照表

分辨率对应DPI ldpi QVGA (240320) mdpi HVGA (320480) hdpi WVGA (480800),FWVGA (480854) xhdpi 720P&#xff08;1280*720&#xff09; xxhdpi 1080p&#xff08;1920*1080 &#xff09; xxxhdpi 4K&#xff08;38402160&#xff09; 手机常见分辨率: 4:3 VGA 640*…