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. CentOS7 nginx 最简单的安装以及设置开机启动

    1. 下载tar包. 2. 解压缩tar包 3. 安装必须的部分 yum包 yum install -y gcc pcre pcre-devel openssl openssl-devel gd gd ...

  2. springBoot2.0配置profile

    1. 使用yaml来配置,直接配置application.yml文件 server: port: 8888 spring: profiles: active: dev # 激活生产环境 --- # 测 ...

  3. x系统清理/tmp/文件夹的原理

    转自:http://www.opsers.org/base/clean-up-on-the-linux-system-tmp-folder-you-may-want-to-know.html§ 我们知 ...

  4. sql server 三角函数

    正弦函数SIN(x)和反正弦函数ASIN(x) --SIN(x)返回x的正弦,其中x为弧度值 --ASIN(x)返回x的反正弦,即正弦x的值,若x不在-1到1的范围内,则返回NULL 示例:selec ...

  5. css实现div水平垂直居中

    中秋快到了,祝大家中秋快乐. 平时大家写bug过程中肯定会遇到让div框水平或者垂直居中,然而有时候能居中,有时候不能居中.我把平时遇到的一些方法写出来,如果对你有用,那便是晴天. 1.text-al ...

  6. elementui 之el-pagination爬坑,属性pager-count的设定

    我想设置总页数为10页,页码条总是显示两个页码,其余省略号显示,我选择了pager-count,如下: <el-pagination @size-change="handleSizeC ...

  7. thinkphp 静态缓存设置

    'HTML_CACHE_RULES'=> array('ActionName' => array('静态规则', '静态缓存有效期', '附加规则'),'ModuleName(小写)' = ...

  8. VMware三种连接方式bridge, nat, host-only

    大家在安装完虚拟机后,默认安装了两个虚拟网卡,VMnet1和 VMnet8,其他的未安装(当然也可以手动安装其他的).其中VMnet1是host网卡,用于host方式连接网络的.VMnet8是NAT网 ...

  9. Laravel 中 Controller访问Model函数/常量

    <?php // User.php class User extends Model { ; //进行中 const USER_TYPE_TEST = 'test'; //测试用户 // 需要在 ...

  10. nginx的rewrite

    nginx服务的rewrite nginx后端服务的指令 1)upstream指令 :设置后端服务器组的主要指令 Upstream name {} 2)server指令:用于设定组内的服务器 3)Ip ...