android异常捕获,android 异常捕获-UncaughtExceptionHandler

在android开发中,异常信息的捕获有多种方式,比如第三方的友盟、蒲公英等,这里主要使用 android 原生的 Thread.UncaughtExceptionHandler 来捕获出现的异常信息,并给出友好的提示,避免出现停止运行,提高用户体验,下面是具体的实现过程。

1.定义自己的异常处理类

新建类 CrashHandler 实现 Thread.UncaughtExceptionHandler接口,如下代码:

public class CrashHandler implements Thread.UncaughtExceptionHandler {

@Override

public void uncaughtException(Thread thread, Throwable ex) {

//回调函数,处理异常出现后的情况

}

}

2.设置该异常类为系统默认的

将上面定义的异常处理类设置为系统默认的异常处理类,当出现异常时,有该类处理。

Thread.setDefaultUncaughtExceptionHandler(crashHandler);

3.具体的实现

为了方便查看和修复异常,这里将出现异常的手机信息和异常信息保存在文件,以便传给服务器,具体实现如下:

import android.content.Context;

import android.content.pm.PackageInfo;

import android.content.pm.PackageManager;

import android.os.Build;

import android.os.Environment;

import android.os.Looper;

import android.util.Log;

import android.widget.Toast;

import java.io.File;

import java.io.FileOutputStream;

import java.io.PrintWriter;

import java.io.StringWriter;

import java.io.Writer;

import java.lang.reflect.Field;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.HashMap;

import java.util.Map;

/**

* 异常管理类

*

* Created by imtianx on 2016-7-10.

*/

public class CrashHandler implements Thread.UncaughtExceptionHandler {

/**

* 系统默认UncaughtExceptionHandler

*/

private Thread.UncaughtExceptionHandler mDefaultHandler;

/**

* context

*/

private Context mContext;

/**

* 存储异常和参数信息

*/

private Map paramsMap = new HashMap<>();

/**

* 格式化时间

*/

private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");

private String TAG = this.getClass().getSimpleName();

private static CrashHandler mInstance;

private CrashHandler() {

}

/**

* 获取CrashHandler实例

*/

public static synchronized CrashHandler getInstance() {

if (null == mInstance) {

mInstance = new CrashHandler();

}

return mInstance;

}

public void init(Context context) {

mContext = context;

mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

//设置该CrashHandler为系统默认的

Thread.setDefaultUncaughtExceptionHandler(this);

}

/**

* uncaughtException 回调函数

*/

@Override

public void uncaughtException(Thread thread, Throwable ex) {

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

//如果自己没处理交给系统处理

mDefaultHandler.uncaughtException(thread, ex);

} else {

//自己处理

try {//延迟3秒杀进程

Thread.sleep(2000);

} catch (InterruptedException e) {

Log.e(TAG, "error : ", e);

}

//退出程序

AppManager.getAppManager().AppExit(mContext);

}

}

/**

* 收集错误信息.发送到服务器

*

* @return 处理了该异常返回true, 否则false

*/

private boolean handleException(Throwable ex) {

if (ex == null) {

return false;

}

//收集设备参数信息

collectDeviceInfo(mContext);

//添加自定义信息

addCustomInfo();

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

new Thread() {

@Override

public void run() {

Looper.prepare();

//在此处处理出现异常的情况

Toast.makeText(mContext, "程序开小差了呢..", Toast.LENGTH_SHORT).show();

Looper.loop();

}

}.start();

//保存日志文件

saveCrashInfo2File(ex);

return true;

}

/**

* 收集设备参数信息

*

* @param ctx

*/

public void collectDeviceInfo(Context ctx) {

//获取versionName,versionCode

try {

PackageManager pm = ctx.getPackageManager();

PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);

if (pi != null) {

String versionName = pi.versionName == null ? "null" : pi.versionName;

String versionCode = pi.versionCode + "";

paramsMap.put("versionName", versionName);

paramsMap.put("versionCode", versionCode);

}

} catch (PackageManager.NameNotFoundException e) {

Log.e(TAG, "an error occured when collect package info", e);

}

//获取所有系统信息

Field[] fields = Build.class.getDeclaredFields();

for (Field field : fields) {

try {

field.setAccessible(true);

paramsMap.put(field.getName(), field.get(null).toString());

} catch (Exception e) {

Log.e(TAG, "an error occured when collect crash info", e);

}

}

}

/**

* 添加自定义参数

*/

private void addCustomInfo() {

Log.i(TAG, "addCustomInfo: 程序出错了...");

}

/**

* 保存错误信息到文件中

*

* @param ex

* @return 返回文件名称, 便于将文件传送到服务器

*/

private String saveCrashInfo2File(Throwable ex) {

StringBuffer sb = new StringBuffer();

for (Map.Entry entry : paramsMap.entrySet()) {

String key = entry.getKey();

String value = entry.getValue();

sb.append(key + "=" + value + "\n");

}

Writer writer = new StringWriter();

PrintWriter printWriter = new PrintWriter(writer);

ex.printStackTrace(printWriter);

Throwable cause = ex.getCause();

while (cause != null) {

cause.printStackTrace(printWriter);

cause = cause.getCause();

}

printWriter.close();

String result = writer.toString();

sb.append(result);

try {

long timestamp = System.currentTimeMillis();

String time = format.format(new Date());

String fileName = "crash-" + time + "-" + timestamp + ".log";

if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/crash/";

File dir = new File(path);

if (!dir.exists()) {

dir.mkdirs();

}

FileOutputStream fos = new FileOutputStream(path + fileName);

fos.write(sb.toString().getBytes());

Log.i(TAG, "saveCrashInfo2File: "+sb.toString());

fos.close();

}

return fileName;

} catch (Exception e) {

Log.e(TAG, "an error occured while writing file...", e);

}

return null;

}

}

注:在上述代码中使用了 AppManager类,是常用的activity 管理类 点此查看

4.使用

在application中初始化,并在配置文件中添加读写权限。

CrashHandler.getInstance().init(this);

到此,全局异常捕获已全部完成。

更多文章请点击此处

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值