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
- Xamarin.Android-捕获未处理异常(全局异常)
一.前言 android中如果出现了未处理的异常,程序会闪退,这是非常不好的用户体验,很多用户会因此卸载APP,因此未处理的异常是应该尽力避免的. 有些很难避免的异常(如:IO.网络等),应在代码中进 ...
- springmvc处理局部异常和全局异常
springmvc通过HandlerExceptionResolver(是一个接口,在spring-webmvc依赖下)处理程序异常,包括处理器异常.数据绑定异常以及处理器执行时发生的异常.Handl ...
- Application中捕获APP中的全局异常
package com.example.administrator.mystudent; import android.app.Application; import android.util.Log ...
- 如何捕获Wince下form程序的全局异常
前言 上两篇文章我们总结了在winform程序下如何捕获全局的异常.那么同样的问题,在wince下我们如何来处理呢?用相同的代码来处理可以吗? 答案是否定的,上面的方案1完全不能解决wince下的情况 ...
- 从壹开始前后端分离 [.netCore 不定期更新 ] 三十五║ 完美实现全局异常日志记录
缘起 哈喽我是不定期更新的日常,昨天群里小伙伴问到了记录日志,当然,以前我也挖过这个坑,后来一直没有来得及填上,也想着 swagger 一直又有错误信息展示的功能,就迟迟没有添加这个功能,不过昨天夜里 ...
- Asp.net Core全局异常监控和记录日志
前言 系统异常监控可以说是重中之重,系统不可能一直运行良好,开发和运维也不可能24小时盯着系统,系统抛异常后我们应当在第一时间收到异常信息.在Asp.net Core里我使用拦截器 ...
- 【spring】-- springboot配置全局异常处理器
一.为什么要使用全局异常处理器? 什么是全局异常处理器? 就是把错误异常统一处理的方法. 应用场景: 1.当你使用jsr303参数校验器,如果参数校验不通过会抛异常,而且无法使用try-catch语句 ...
- SprimgMVC学习笔记(六)—— 全局异常的处理
一.处理思路 springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑. 系统中异常包括两类:预期异常和运行时异常RuntimeExcept ...
- 【转】 Android自定义捕获Application全局异常
大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试,所以在程序发布出去之后,如果出现了 ...
随机推荐
- Linux系统管理和调优(内存、CPU、磁盘IO、网络)
系统管理 Author:Rich七哥 查看 CPU 负载相关工具,找出系统中使用 CPU 最多的进程 查看 Memory 运行状态相关工具,找出系统中使用内存最多的进程 查看 IO 运行状态相关工具, ...
- etcd集群移除节点
查看当前集群信息 # etcdctl member list --write-out=table +------------------+---------+--------------------+ ...
- Vue 子组件,向父组件传递。
- springMVC原理简单介绍
说明: 用户发送请求到DispatcherServlet,即前端控制器 DipatcherServlet调用处理器映射器HandlerMapping解析 处理器映射器HandlerMapping根据请 ...
- 【7.10校内test】T2不等数列
[题目链接luogu] 此题在luogu上模数是2015,考试题的模数是2012. 然后这道题听说好多人是打表找规律的(就像7.9T2一样)(手动滑稽_gc) 另外手动 sy,每次测试都无意之间bib ...
- python一行代码打印Love心形
用Python画一颗特别的爱心,送给那个特别的她,给她一份浪漫的惊喜吧 print('\n'.join([''.join([('Love'[(x-y) % len('Love')] if ((x*0. ...
- Java基础——Modifier类
转自:https://www.cnblogs.com/baiqiantao/p/7478523.html 反射 Reflect Modifier 修饰符工具类 在查看反射相关的Class.Fiel ...
- 服务安全之:JWT
JWT是JSON Web Tokens的缩写.既然叫JSON Web Tokens,所以JWT Tokens中真正包含的是多个JSON对象.为什么是多个JSON对象呢?因为SWT Token实际 ...
- 20.AutoMapper 之理解你的映射(Understanding Your Mappings)
https://www.jianshu.com/p/4f5c14fbf1c2 理解你的映射(Understanding Your Mappings) AutoMapper 为你的映射创建执行计划.在调 ...
- 03-Spring基于xml的IOC配置--spring的依赖注入
1.概念 依赖注入:Dependency Injection(简称DI注入).它是 spring 框架核心 ioc 的具体实现. 简单理解:可以在一个类中不通过new的方式依赖其它对象.目的是为了解耦 ...