Android编程实现捕获程序异常退出时的错误log信息功能详解
发布时间 - 2026-01-11 03:02:56 点击率:次本文实例讲述了Android编程实现捕获程序异常退出时的错误log信息功能。分享给大家供大家参考,具体如下:

很多时候我们程序无缘无故的就挂掉了,让我们一头雾水,如果刚好我们在调试,那我们可以通过错误log来查看是什么原因引起的程序崩溃。但是当我们把程序发别人使用时,就没那么好运了,那我们要怎么样才能捕获到那个错误异常呢?还好Android给我们提供了UncaughtExceptionHandler 这个类,我们可以通过实现这个类的接口,来全局捕获那个让程序崩掉的错误log信息。可以将错误的log保存在本地,也可以发送给服务器后台。下面来看下UncaughtExceptionHandler 的实现类CrashHandler吧。
CrashHandler.Java
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
public class CrashHandler implements UncaughtExceptionHandler {
private static final String TAG = CrashHandler.class.getSimpleName();
private static final String SINGLE_RETURN = "\n";
private static final String SINGLE_LINE = "--------------------------------";
private static CrashHandler mCrashHandler;
private Context mContext;
private UncaughtExceptionHandler mDefaultHandler;
private StringBuffer mErrorLogBuffer = new StringBuffer();
/**
* 获取CrashHandler实例,单例模式。
*
* @return 返回CrashHandler实例
*/
public static CrashHandler getInstance() {
if (mCrashHandler == null) {
synchronized (CrashHandler.class) {
if (mCrashHandler == null) {
mCrashHandler = new CrashHandler();
}
}
}
return mCrashHandler;
}
public void init(Context context) {
mContext = context;
// 获取系统默认的uncaughtException处理类实例
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// 设置成我们处理uncaughtException的类
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.d(TAG, "uncaughtException:" + ex);
if (!handleException(ex) && mDefaultHandler != null) {
// 如果用户没有处理异常就由系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
} else {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
android.os.Process.killProcess(android.os.Process.myPid());
}
}
//处理异常事件
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_SHORT)
.show();
Looper.loop();
}
}).start();
// 收集设备参数信息
collectDeviceInfo(mContext);
// 收集错误日志
collectCrashInfo(ex);
// 保存错误日志
saveErrorLog();
//TODO: 这里可以加一个网络的请求,发送错误log给后台
// sendErrorLog();
return true;
}
//保存日志到/mnt/sdcard/AppLog/目录下,文件名已时间yyyy-MM-dd_hh-mm-ss.log的形式保存
private void saveErrorLog() {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss", Locale.getDefault());
String format = sdf.format(new Date());
format += ".log";
String path = Environment.getExternalStorageDirectory().getPath()+"/AppLog/";
File file = new File(path);
if (!file.exists()){
file.mkdirs();
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(path+format);
fos.write(mErrorLogBuffer.toString().getBytes());
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
fos = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
//收集错误信息
private void collectCrashInfo(Throwable ex) {
Writer info = new StringWriter();
PrintWriter printWriter = new PrintWriter(info);
ex.printStackTrace(printWriter);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
String result = info.toString();
printWriter.close();
//将错误信息加入mErrorLogBuffer中
append("", result);
mErrorLogBuffer.append(SINGLE_LINE + SINGLE_RETURN);
Log.d(TAG, "saveCrashInfo2File:" + mErrorLogBuffer.toString());
}
//收集应用和设备信息
private void collectDeviceInfo(Context context) {
//每次使用前,清掉mErrorLogBuffer里的内容
mErrorLogBuffer.setLength(0);
mErrorLogBuffer.append(SINGLE_RETURN + SINGLE_LINE + SINGLE_RETURN);
//获取应用的信息
PackageManager pm = context.getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(context.getPackageName(),
PackageManager.GET_ACTIVITIES);
if (pi != null) {
append("versionCode", pi.versionCode);
append("versionName", pi.versionName);
append("packageName", pi.packageName);
}
} catch (NameNotFoundException e) {
e.printStackTrace();
}
mErrorLogBuffer.append(SINGLE_LINE + SINGLE_RETURN);
//获取设备的信息
Field[] fields = Build.class.getDeclaredFields();
getDeviceInfoByReflection(fields);
fields = Build.VERSION.class.getDeclaredFields();
getDeviceInfoByReflection(fields);
mErrorLogBuffer.append(SINGLE_LINE + SINGLE_RETURN);
}
//获取设备的信息通过反射方式
private void getDeviceInfoByReflection(Field[] fields) {
for (Field field : fields) {
try {
field.setAccessible(true);
append(field.getName(), field.get(null));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
//mErrorLogBuffer添加友好的log信息
private void append(String key, Object value) {
mErrorLogBuffer.append("" + key + ":" + value + SINGLE_RETURN);
}
}
在application中的使用非常简单,只要init就好了,之后我们就只要等异常出现吧。
CrashApplication.java
import android.app.Application;
public class CrashApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
CrashHandler.getInstance().init(this);
}
}
不要忘记在AndroidManifest.xml声明我们的CrashApplication 。
AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:name=".CrashApplication"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.crashtestdemo.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android编程之activity操作技巧总结》、《Android操作json格式数据技巧总结》、《Android数据库操作技巧总结》、《Android文件操作技巧汇总》、《Android资源操作技巧汇总》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。
# Android
# 捕获
# 程序
# 异常
# 退出
# 错误
# log
# 信息
# Android获取apk程序签名信息代码示例
# Android实现获取应用程序相关信息列表的方法
# Android开发之在程序中时时获取logcat日志信息的方法(附demo源码下载)
# 如何判断软件程序是否联网 联网状态提示信息Android实现
# Android实现整理PackageManager获取所有安装程序信息
# Android ApplicationInfo 应用程序信息的详解
# Android编程获取APP应用程序基本信息辅助类【APP名称、包名、图标
# 版本号等】
# Android获取手机型号/系统版本号/App版本号等信息实例讲解
# Android开发获取系统中已安装程序信息的方法
# 操作技巧
# 错误信息
# 进阶
# 相关内容
# 让我们
# 给我们
# 感兴趣
# 我们可以
# 就没
# 可以通过
# 给大家
# 掉了
# 当我们
# 无缘无故
# 更多关于
# 解决方法
# 所述
# 很抱歉
# 程序设计
# 就由
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何在云主机上快速搭建网站?
Laravel模型关联查询教程_Laravel Eloquent一对多关联写法
1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤
常州企业网站制作公司,全国继续教育网怎么登录?
使用spring连接及操作mongodb3.0实例
Laravel怎么使用artisan命令缓存配置和视图
ChatGPT常用指令模板大全 新手快速上手的万能Prompt合集
Laravel如何创建自定义Facades?(详细步骤)
Laravel如何实现数据导出到PDF_Laravel使用snappy生成网页快照PDF【方案】
图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?
如何在阿里云ECS服务器部署织梦CMS网站?
JavaScript中的标签模板是什么_它如何扩展字符串功能
如何注册花生壳免费域名并搭建个人网站?
制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?
Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程
Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门
Laravel如何实现全文搜索功能?(Scout和Algolia示例)
米侠浏览器网页背景异常怎么办 米侠显示修复
如何在搬瓦工VPS快速搭建网站?
Laravel Octane如何提升性能_使用Laravel Octane加速你的应用
公司门户网站制作流程,华为官网怎么做?
Laravel集合Collection怎么用_Laravel集合常用函数详解
如何批量查询域名的建站时间记录?
Laravel的.env文件有什么用_Laravel环境变量配置与管理详解
js实现获取鼠标当前的位置
如何在建站宝盒中设置产品搜索功能?
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?
如何在 Pandas 中基于一列条件计算另一列的分组均值
怎样使用JSON进行数据交换_它有什么限制
php静态变量怎么调试_php静态变量作用域调试技巧【解答】
Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置
Laravel如何自定义错误页面(404, 500)?(代码示例)
Laravel如何使用withoutEvents方法临时禁用模型事件
iOS发送验证码倒计时应用
百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏
Laravel怎么实现模型属性的自动加密
网站制作壁纸教程视频,电脑壁纸网站?
laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析
如何在Windows服务器上快速搭建网站?
canvas 画布在主流浏览器中的尺寸限制详细介绍
Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)
javascript中的数组方法有哪些_如何利用数组方法简化数据处理
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
如何在自有机房高效搭建专业网站?
C语言设计一个闪闪的圣诞树
Laravel如何使用Contracts(契约)进行编程_Laravel契约接口与依赖反转
Laravel如何升级到最新版本?(升级指南和步骤)
Android滚轮选择时间控件使用详解
如何选择可靠的免备案建站服务器?

