程序员最头疼的事情就是bug和debug。这次debug长达20天,搞的我心力交瘁。累,因为Android兼容性,不同手机会有不同的bug出来,而且很难复现,所以就上网找了下类似保存错误log到文件再上传到服务器,现把源码也共享出来。上传至服务器的代码我没加。相信大家都有现成的代码了。

先讲下原理,跟JavaEE的自定义异常捕获一样,将错误一直向上抛,然后在最上层统一处理。这里就可以获得Exception Message,进行保存操作

异常捕获类如下:

/**

* @author Stay

*      在Application中统一捕获异常,保存到文件中下次再打开时上传

*/

public class CrashHandler implements UncaughtExceptionHandler {

/** 是否开启日志输出,在Debug状态下开启,

* 在Release状态下关闭以提示程序性能

* */

public static final boolean DEBUG = true;

/** 系统默认的UncaughtException处理类 */

private Thread.UncaughtExceptionHandler mDefaultHandler;

/** CrashHandler实例 */

private static CrashHandler INSTANCE;

/** 程序的Context对象 */

//    private Context mContext;

/** 保证只有一个CrashHandler实例 */

private CrashHandler() {}

/** 获取CrashHandler实例 ,单例模式*/

public static CrashHandler getInstance() {

if (INSTANCE == null) {

INSTANCE = new CrashHandler();

}

return INSTANCE;

}

/**

* 初始化,注册Context对象,

* 获取系统默认的UncaughtException处理器,

* 设置该CrashHandler为程序的默认处理器

*

* @param ctx

*/

public void init(Context ctx) {

//        mContext = ctx;

mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

Thread.setDefaultUncaughtExceptionHandler(this);

}

/**

* 当UncaughtException发生时会转入该函数来处理

*/

@Override

public void uncaughtException(Thread thread, Throwable ex) {

if (!handleException(ex) && mDefaultHandler != null) {

//如果用户没有处理则让系统默认的异常处理器来处理

mDefaultHandler.uncaughtException(thread, ex);

} else {  //如果自己处理了异常,则不会弹出错误对话框,则需要手动退出app

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

}

android.os.Process.killProcess(android.os.Process.myPid());

System.exit(10);

}

}

/**

* 自定义错误处理,收集错误信息

* 发送错误报告等操作均在此完成.

* 开发者可以根据自己的情况来自定义异常处理逻辑

* @return

* true代表处理该异常,不再向上抛异常,

* false代表不处理该异常(可以将该log信息存储起来)然后交给上层(这里就到了系统的异常处理)去处理,

* 简单来说就是true不会弹出那个错误提示框,false就会弹出

*/

private boolean handleException(final Throwable ex) {

if (ex == null) {

return false;

}

//        final String msg = ex.getLocalizedMessage();

final StackTraceElement[] stack = ex.getStackTrace();

final String message = ex.getMessage();

//使用Toast来显示异常信息

new Thread() {

@Override

public void run() {

Looper.prepare();

//                Toast.makeText(mContext, "程序出错啦:" + message, Toast.LENGTH_LONG).show();

//                可以只创建一个文件,以后全部往里面append然后发送,这样就会有重复的信息,个人不推荐

String fileName = "crash-" + System.currentTimeMillis()  + ".log";

File file = new File(Environment.getExternalStorageDirectory(), fileName);

try {

FileOutputStream fos = new FileOutputStream(file,true);

fos.write(message.getBytes());

for (int i = 0; i < stack.length; i++) {

fos.write(stack[i].toString().getBytes());

}

fos.flush();

fos.close();

} catch (Exception e) {

}

Looper.loop();

}

}.start();

return false;

}

// TODO 使用HTTP Post 发送错误报告到服务器  这里不再赘述

//    private void postReport(File file) {

//      在上传的时候还可以将该app的version,该手机的机型等信息一并发送的服务器,

//      Android的兼容性众所周知,所以可能错误不是每个手机都会报错,还是有针对性的去debug比较好

//    }

}

在Application onCreate时就注册ExceptionHandler,此后只要程序在抛异常后就能捕获到。

public class App extends Application{

@Override

public void onCreate() {

super.onCreate();

CrashHandler crashHandler = CrashHandler.getInstance();

//注册crashHandler

crashHandler.init(getApplicationContext());

}

}

?public class LogActivity extends Activity {

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

try {//制造bug

File file = new File(Environment.getExternalStorageState() ,"crash.bin");

FileInputStream fis = new FileInputStream(file);

byte[] buffer = new byte[1024];

fis.read(buffer);

} catch (Exception e) {

//这里不能再向上抛异常,如果想要将log信息保存起来,则抛出runtime异常,

//          让自定义的handler来捕获,统一将文件保存起来上传

throw new RuntimeException(e);

}

}

}

注意,如果catch后不throw就默认是自己处理了,ExceptionHandler不会捕获异常了。再分享一个Log的封装类,只要在这里设置DEBUG的值就能让控制台是否打印出log

public class DebugUtil {

public static final String TAG = "ICON";

public static final boolean DEBUG = true;

public static void toast(Context context,String content){

Toast.makeText(context, content, Toast.LENGTH_SHORT).show();

}

public static void debug(String tag,String msg){

if (DEBUG) {

Log.d(tag, msg);

}

}

public static void debug(String msg){

if (DEBUG) {

Log.d(TAG, msg);

}

}

public static void error(String tag,String error){

Log.e(tag, error);

}

public static void error(String error){

Log.e(TAG, error);

}

}

android 监测bug上传到服务器,基于Android 错误信息捕获发送至服务器的详解相关推荐

  1. php图片上传腾讯云cos,ThinkPHP集成腾讯云存储(COS)--详解

    准备工作: 一. 根据图示进入COS 点击立即使用 进入后根据下面点击新建:Bucket(Bucket就是你往云存储的一个目录) 新建Bucket 二. 下载SDK 下一步: 然后复制把整个cos文件 ...

  2. FTP编程实验——实现文件上传下载(基于Python3.7和PyQt5)

    目录 FTP编程实现文件上传下载(基于Python3.7和PyQt5) 一.实验目的 二.实验内容 三.实验步骤 (一)服务器端 (二)客户端 [1] 界面设计 [2] 生成布局代码 [3] 功能实现 ...

  3. Android开发文件上传格式,(android开发)使用okhttp上传文件

    开发android手机客户端,常常会需要上传文件到服务器,比如:你手机里的照片. 使用okhttp会是一个很好的选择.它使用很简单,而且运行效率也很高. 首先,在 app/build.gradle 的 ...

  4. lede更改软件源_Linux的上传和下载——Ubuntu中软件的安装和ftp服务器的搭建

    [Linux操作系统]Linux的上传和下载--Ubuntu中软件的安装和ftp服务器的搭建 学习完Linux终端命令以后,我们现在要考虑的是怎么实现Linux中文件的上传和下载,这就是我们本篇博客要 ...

  5. android multipartentity 怎么上传参数,android-通过MultipartEntityBuilder通过HTTP表单上传文件,并显示进度b...

    android-通过MultipartEntityBuilder通过HTTP表单上传文件,并显示进度b 短版本-.jar已弃用,其升级版本java.lang.NoClassDefFoundError在 ...

  6. 九宫格拼图android代码,Android 多图上传后将图片进行九宫格展示的实例代码

    不多说上代码 public abstract class NineGridAdapter { protected Context context; protected List list; publi ...

  7. RxHttp 完美适配Android 10/11 上传/下载/进度监听

    1.前言 随着Android 11的正式发布,适配Android 10/11 分区存储就更加的迫切了,因为Android 11开始,将强制开启分区存储,我们就无法再以绝对路径的方式去读写非沙盒目录下的 ...

  8. 魅族android不兼容Android,魅族17系列彻底跟上时代,搭载基于Android 10的Flyme 8.1系统...

    原标题:魅族17系列彻底跟上时代,搭载基于Android 10的Flyme 8.1系统 我们知道,魅族17年匠心工艺大作暨魅族科技第一部5G高端旗舰手机魅族17系列手机将于5月8日正式发布,经过最近这 ...

  9. android多文件上传错误,微信多图上传解决android多图上传失败问题

    微信提供了文件上传的方法wx.uploadFile来上传我们的图片 wx.chooseImage({ success: function(res) { var tempFilePaths = res. ...

最新文章

  1. 第十九章——使用资源调控器管理资源(2)——使用T-SQL配置资源调控器
  2. Python Tkinter小试
  3. Flink从入门到精通100篇(十九)-基于 Flink 的大规模准实时数据分析平台的建设实践
  4. 在MAC系统的eclipse里打开android sdk manager
  5. 什么是XSS攻击XSS攻击应用场景
  6. art-template入门(六)之解析规则
  7. 为什么要远离对日外包_远离魔法-或:为什么我不想再使用Laravel
  8. windows下shutdown/up oracle数据库的批处理
  9. 如何做好一位合格qc_如何做好一个合格的热缩产品
  10. K8S知道,K9S呢?
  11. 高中低压电网光伏并网二次设计——分布式光伏电站并网市电通讯组网
  12. Vue使用iconfont图标
  13. 2020图灵奖颁给“龙书”两位作者!合作数十年,他们让计算机读懂码农代码
  14. Vue中使用 Aplayer 和 Metingjs 添加音乐插件
  15. 2021 TCR Asia收官 壳牌捷凯领克东望洋收获大满贯
  16. oracle表数据导出成unl文件,oracle的文本导入、导出技巧
  17. Unity3D新手入门初中高级教程
  18. java代码自动抠图_Opencv java实现人脸抠图和行为识别
  19. 雷蛇 笔记本 装linux,顺应民意:雷蛇考虑开发Linux版Blade游戏本
  20. linux操作系统 第09章 操作系统接口

热门文章

  1. mysql 线性表_线性表之顺序存储,基本操作
  2. SparkCore基础
  3. Java什么是重用_深度解析:java必须掌握的知识点——类的重用
  4. 如何在计算机课上渗透德育教育初探,在《道德与法治》课中德育渗透的案例初探...
  5. 论文浅尝 - ACL2020 | 通过集成知识转换进行多语言知识图谱补全
  6. 关于PaddleNLP如何加载训练好的模型进行NER
  7. 论文解读:Attention is All you need
  8. CRISP-DM:数据挖掘标准流程
  9. 最小生成树——普里姆算法和克鲁斯卡尔算法
  10. day21 面向对象之继承和组合