public class CrashHandler implements UncaughtExceptionHandler
{
private static CrashHandler instance;
 
public static final String TAG = "CrashHandler";
 
private static final String VERSION_NAME = "versionName";
 
private static final String VERSION_CODE = "versionCode";
 
private static final String STACK_TRACE = "STACK_TRACE";
 
private Thread.UncaughtExceptionHandler mDefaultHandler;
 
private Context mContext;
 
private static final String CRASH_REPORTER_EXTENSION = ".cr";
private Properties deviceCrashInfo = new Properties();
 
private CrashHandler()
{
}
 
public static synchronized CrashHandler getInstance()
{
if (instance == null)
{
instance = new CrashHandler();
}
return instance;
}
 
public void init(Context ctx)
{
this.mContext = ctx;
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
 
@Override
public void uncaughtException(Thread thread, Throwable ex)
{
if (mDefaultHandler != null && !handlerException(ex))
{
// 如果用户没有进行异常处理就让系统默认的处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
} else
{
exitApp();
}
}
 
private boolean handlerException(Throwable ex)
{
if (ex == null)
{
return true;
}
final String msg = ex.getLocalizedMessage();
new Thread() {
@Override
public void run()
{
Looper.prepare();
Toast toast = Toast.makeText(mContext, "程序出错啦!" + msg, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
Looper.loop();
}
}.start();
// 收集设备信息
collectDeviceInfo(mContext);
// 保存错误
saveCrashInfoToFiles(ex);
// 发送错误报告到服务器
sendCrashReportsToServer(mContext);
return true;
}
 
private void collectDeviceInfo(Context ctx)
{
try
{
PackageManager pm = ctx.getPackageManager();
PackageInfo pi = pm.getPackageArchiveInfo(ctx.getPackageName(),
PackageManager.GET_ACTIVITIES);
if (pi != null)
{
deviceCrashInfo.put(VERSION_NAME, pi.versionName == null ? "not set"
: pi.versionName);
deviceCrashInfo.put(VERSION_CODE, pi.versionCode);
}
} catch (Exception e)
{
Log.e(TAG, "error occured when collecting crash info" + e);
}
 
// 使用反射来收集设备信息.在Build类中包含各种设备信息,
// 例如: 系统版本号,设备生产商 等帮助调试程序的有用信息
// 具体信息请参考后面的截图
Field[] fields = Builder.class.getDeclaredFields();
for (Field field : fields)
{
try
{
field.setAccessible(true);
deviceCrashInfo.put(field.getName(), null);
} catch (Exception e)
{
Log.e(TAG, "error occured when collecting device info" + e);
}
}
}
 
private String saveCrashInfoToFiles(Throwable ex)
{
Writer info = new StringWriter();
PrintWriter printWriter = new PrintWriter(info);
ex.printStackTrace(printWriter);
 
Throwable cause = ex.getCause();
while (cause != null)
{
ex.printStackTrace(printWriter);
cause = cause.getCause();
}
 
String result = info.toString();
printWriter.close();
deviceCrashInfo.put("EXCEPTION", ex.getLocalizedMessage());
deviceCrashInfo.put(STACK_TRACE, result);
 
try
{
long time = System.currentTimeMillis();
String filename = "crash-" + time + CRASH_REPORTER_EXTENSION;
FileOutputStream trace = mContext.openFileOutput(filename, Context.MODE_PRIVATE);
 
deviceCrashInfo.store(trace, "");
trace.flush();
trace.close();
} catch (Exception e)
{
Log.e(TAG, "error occured when save crashinfo to files" + e);
}
return null;
}
 
private void sendCrashReportsToServer(Context ctx)
{
String[] crFiles = getCrashReportFiles(ctx);
if (crFiles != null && crFiles.length > 0)
{
TreeSet<String> sortedFiles = new TreeSet<String>();
sortedFiles.addAll(Arrays.asList(crFiles));
for (String fileName : sortedFiles)
{
File cr = new File(ctx.getFilesDir(), fileName);
postReport(cr);
cr.delete();// 删除已发送的报告
}
}
}
 
private void postReport(File file)
{
// TODO 发送错误报告到服务器
}
 
private String[] getCrashReportFiles(Context ctx)
{
File filesDir = ctx.getFilesDir();
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name)
{
return name.endsWith(CRASH_REPORTER_EXTENSION);
}
};
return filesDir.list(filter);
}
 
private void exitApp()
{
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
}
 
结伴旅游网,一个免费的交友网站:www.jieberu.com
推推族,免费得门票,游景区:www.tuituizu.com

Android处理未捕获的异常(应用全局异常)的更多相关文章

  1. Xamarin.Android-捕获未处理异常(全局异常)

    一.前言 android中如果出现了未处理的异常,程序会闪退,这是非常不好的用户体验,很多用户会因此卸载APP,因此未处理的异常是应该尽力避免的. 有些很难避免的异常(如:IO.网络等),应在代码中进 ...

  2. springmvc处理局部异常和全局异常

    springmvc通过HandlerExceptionResolver(是一个接口,在spring-webmvc依赖下)处理程序异常,包括处理器异常.数据绑定异常以及处理器执行时发生的异常.Handl ...

  3. Application中捕获APP中的全局异常

    package com.example.administrator.mystudent; import android.app.Application; import android.util.Log ...

  4. 如何捕获Wince下form程序的全局异常

    前言 上两篇文章我们总结了在winform程序下如何捕获全局的异常.那么同样的问题,在wince下我们如何来处理呢?用相同的代码来处理可以吗? 答案是否定的,上面的方案1完全不能解决wince下的情况 ...

  5. 从壹开始前后端分离 [.netCore 不定期更新 ] 三十五║ 完美实现全局异常日志记录

    缘起 哈喽我是不定期更新的日常,昨天群里小伙伴问到了记录日志,当然,以前我也挖过这个坑,后来一直没有来得及填上,也想着 swagger 一直又有错误信息展示的功能,就迟迟没有添加这个功能,不过昨天夜里 ...

  6. Asp.net Core全局异常监控和记录日志

    前言           系统异常监控可以说是重中之重,系统不可能一直运行良好,开发和运维也不可能24小时盯着系统,系统抛异常后我们应当在第一时间收到异常信息.在Asp.net Core里我使用拦截器 ...

  7. 【spring】-- springboot配置全局异常处理器

    一.为什么要使用全局异常处理器? 什么是全局异常处理器? 就是把错误异常统一处理的方法. 应用场景: 1.当你使用jsr303参数校验器,如果参数校验不通过会抛异常,而且无法使用try-catch语句 ...

  8. SprimgMVC学习笔记(六)—— 全局异常的处理

    一.处理思路 springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑. 系统中异常包括两类:预期异常和运行时异常RuntimeExcept ...

  9. 【转】 Android自定义捕获Application全局异常

    大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试,所以在程序发布出去之后,如果出现了 ...

随机推荐

  1. Java Web - 笔记(1)

    1.web.xml Attribute "xmlns:xsi" must be declared for element type "web-app"相关报错解 ...

  2. 02:Redis常见面试题

    1.1 redis基础面试题 1.什么是Redis?简述它的优缺点? 1. Redis本质上是一个Key-Value类型的内存数据库,很像memcached. 2. 整个数据库统统加载在内存当中进行操 ...

  3. MongoDB数据库的操作

    一.操作MongoDB数据库 1.创建数据库 语法:ues 注意:如果数据库不存在则再创建数据库,否则切换到指定的 数据库!如果刚刚创建的数据不在列表中,如果需要显示这个数 据库,那么需要在刚刚创建的 ...

  4. 主成分分析法详解(PCA)

    引用:https://blog.csdn.net/program_developer/article/details/80632779 将n维特征映射到k维上,只保留包含绝大部分方差的维度特征,而忽略 ...

  5. MyBatis的Insert操作详解

    一.前言 数据库操作怎能少了INSERT操作呢?下面记录MyBatis关于INSERT操作的笔记,以便日后查阅. 二. insert元素 属性详解 其属性如下: parameterType ,入参的全 ...

  6. npm学习(七)之如何发布包、更新发布包、删除发布包

    前言 我们经常使用npm来下载别人的模块或者说包,那么我们如何将自己写的模块上传到npm呢? 了解npm政策 在开始之前,最好回顾一下npm的政策,以防您对站点礼仪.命名.许可或其他指导原则有疑问. ...

  7. luogu P1758 [NOI2009]管道取珠

    luogu 这个题中的平方有点东西,考虑他的组合意义,也就是做这个过程两次,如果两次得到的结果一样就给答案+1,所以可以考虑dp,设\(f_{i,j,k,l}\)表示第一个过程中上面取到的第\(i\) ...

  8. mac StarUML3.0.2破解

    mac StarUML3.0.2破解 StarUML是一款开放源码的UML开发工具,是由韩国公司主导开发出来的产品,可以直接到StarUML网站下载.可以用来创建UML类图. 破解办法是通过asar工 ...

  9. Spring boot 拦截器和过滤器

    1. 过滤器 Filter介绍 Filter可以认为是Servlet的一种“加强版”,是对Servlet的扩展(既可以对请求进行预处理,又可以对处理结果进行后续处理.使用Filter完整的一般流程是: ...

  10. 使用SQLyog对mysql数据库的数据结构进行导出、导入

    主要分为两个步骤: 一.使用SQLyog对mysql数据库的数据结构进行导出 1.鼠标右键选择需要导出数据结构的数据库——>点击[备份/导出]——>点击[备份数据库,转储到SQL....] ...