android 自定义异常,Android自定义异常处理

一、为何使用

项目上线后,程序有可能发生崩溃现象,但是开发人员并不知道那个地方出错了,无法看到崩溃日志。这就需要我们自定义Android异常处理,当项目发生崩溃时,将错误日志保存起来,待用户再次启动app的时候,讲这个错误日志发送给服务器,我们程序员再做相应的解决。

二、解决思路

自定义类CrashHandler实现UncaughtExceptionHandler接口,手动捕捉异常。

application中设置该CrashHandler为程序的默认处理器。(init方法)

baseActivity中调用application中的init方法。

CrashHandler类中将捕获的异常保存到本地SqLite数据库中。

用户再次启动App时,遍历本地SqLite数据路,如果有数据,发送到服务器,发送完成后删除;如果没有数据,跳过。

三、具体实现

自定义CrashHandler

public class AsExceptionHandler implements UncaughtExceptionHandler {

private UncaughtExceptionHandler mDefaultHandler;

public static final String TAG = "CatchExcep";

//自定义的Application类

AsExceptionApplication application;

Activity myActivity;

// 用来存储设备信息和异常信息

private Map info = new HashMap();

public AsExceptionHandler(AsExceptionApplication application, Activity myActivity) {

// 获取系统默认的UncaughtException处理器

mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

this.application = application;

this.myActivity = myActivity;

Class> cxx = myActivity.getClass();

}

@Override

public void uncaughtException(Thread thread, Throwable ex) {

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

// 如果用户没有处理则让系统默认的异常处理器来处理

mDefaultHandler.uncaughtException(thread, ex);

} else {

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

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

}

//关闭所有Activity,退出程序

application.finishActivity();

}

}

/**

* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. *

* @param ex

* @return true:如果处理了该异常信息;否则返回false.

*/

private boolean handleException(Throwable ex) {

if (ex == null) {

return false;

}

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

new Thread() {

@Override

public void run() {

Looper.prepare();

Toast.makeText(application.getApplicationContext(), "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_SHORT).show();

Looper.loop();

}

}.start();

// 收集设备参数信息

collectDeviceInfo(application);

// 保存日志文件

saveCrashInfo2File(ex, application);

return true;

}

/**

* 收集设备参数信息

*

* @param context

*/

public void collectDeviceInfo(Context context) {

try {

// 获得包管理器

PackageManager pm = context.getPackageManager();

// 得到该应用的信息,即主Activity

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

if (pi != null) {

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

String versionCode = pi.versionCode + "";

info.put("versionName", versionName);

info.put("versionCode", versionCode);

info.put("my_name", "suibian");

}

} catch (NameNotFoundException e) {

e.printStackTrace();

}

Field[] fields = Build.class.getDeclaredFields();// 反射机制

for (Field field : fields) {

try {

field.setAccessible(true);

info.put(field.getName(), field.get("").toString());

Log.d(TAG, field.getName() + ":" + field.get(""));

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

}

// sqlite数据库

private DB db;

private String saveCrashInfo2File(Throwable ex, Context context) {

StringBuffer sb = new StringBuffer();

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

String key = entry.getKey();

String value = entry.getValue();

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

Log.e(key, value);

}

Writer writer = new StringWriter();

PrintWriter pw = new PrintWriter(writer);

ex.printStackTrace(pw);

Throwable cause = ex.getCause();

// 循环着把所有的异常信息写入writer中

while (cause != null) {

cause.printStackTrace(pw);

cause = cause.getCause();

}

pw.close();// 记得关闭

String result = writer.toString();

Log.e("错误日志", result);

sb.append(result);

// 保存错误日志到本地

// 获取当时时间

SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss ");

Date curDate = new Date(System.currentTimeMillis());// 获取当前时间

String time = formatter.format(curDate);

db = new DB(context);

// 写

SQLiteDatabase dbwrite = db.getWritableDatabase();

//

ContentValues cv = new ContentValues();

cv.put("text", sb.toString());

cv.put("time", time);

// 写入

dbwrite.insert("record", null, cv);

// 关闭

dbwrite.close();

return null;

}}

自定义Application

ArrayList list = new ArrayList();

public void init(Activity myActivity) {

// 设置该CrashHandler为程序的默认处理器

AsExceptionHandler catchExcep = new AsExceptionHandler(this, myActivity);

Thread.setDefaultUncaughtExceptionHandler(catchExcep);}

/**

* 向Activity列表中添加Activity对象

*/

public void addActivity(Activity a) {

list.add(a);}

/**

* 关闭Activity列表中的所有Activity

*/

public void finishActivity() {

for (Activity activity : list) {

if (null != activity) {

activity.finish();

}

}

// 杀死该应用进程

android.os.Process.killProcess(android.os.Process.myPid());}

BaseActivity

onCreate()方法中

application = (AsExceptionApplication) getApplication();

application.init(this); // 把 this 传过去,,这里主要是要 得到当前的或者是出错的activity的包名和类名// 其实这里也可以,把获取的数据,,传过去,,不用传对象;;;

application.addActivity(this);

//进入应用首页 查询sqlite数据库中管是否有错误日志---若有 发送并删除--- 没有则关闭

private void sendError() {

db = new DB(mContext);

SQLiteDatabase dbread = db.getReadableDatabase();

SQLiteDatabase dbwrite = db.getWritableDatabase();

Cursor c = dbread.query("record", null, null, null, null, null, null);

while (c.moveToNext()) {

String word = c.getString(c.getColumnIndex("text"));

String time = c.getString(c.getColumnIndex("time"));

Toast.makeText(mContext, word, Toast.LENGTH_SHORT).show();

}

//删除错误日志

dbwrite.delete("record", null, null);

// 关闭

dbread.close();

dbwrite.close();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值