Android 全局异常捕获实例详解
程序员文章站
2023-12-03 12:29:58
android 全局异常捕获
今天就来说说作为程序猿的我们每天都会遇到的东西bug,出bug不可怕可怕的是没有出bug时的堆栈信息,那么对于bug的信息收集就显得尤为重要...
android 全局异常捕获
今天就来说说作为程序猿的我们每天都会遇到的东西bug,出bug不可怕可怕的是没有出bug时的堆栈信息,那么对于bug的信息收集就显得尤为重要了,一般用第三方bugly或者友盟等等都能轻易收集,但是由于公司不让使用第三方,而安卓正好有原生的异常收集类uncaughtexceptionhandler,那么今天博客就从这个类开始.
uncaughtexceptionhandler见名知意,即他是处理我们未捕获的异常,具体使用分两步
1.实现我们自己的异常处理类
public class crashhandler implements thread.uncaughtexceptionhandler { @override public void uncaughtexception(thread thread, throwable ex) { } }
需要我们实现thread.uncaughtexceptionhandler接口当有未捕获的异常的时候会回调uncaughtexception(thread thread, throwable ex)方法
2.设置该crashhandler为系统默认的
thread.setdefaultuncaughtexceptionhandler(crashhandler);
以上只是使用步骤的介绍,具体项目中的使用我直接贴代码
在application中初始化
package com.zly.www.basedemo.base; import android.app.application; import android.content.context; import com.zly.www.basedemo.exception.crashhandler; /** * created by zly on 2016/6/11. */ public class appapplication extends application { private static context mcontext; @override public void oncreate() { super.oncreate(); this.mcontext = this; crashhandler.getinstance().init(this);//初始化全局异常管理 } public static context getcontext(){ return mcontext; } }
crashhandler 实现类如下
package com.zly.www.basedemo.exception; 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 com.zly.www.basedemo.utils.appmanager; 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 zly on 2016/7/3. */ public class crashhandler implements thread.uncaughtexceptionhandler { /** * 系统默认uncaughtexceptionhandler */ private thread.uncaughtexceptionhandler mdefaulthandler; /** * context */ private context mcontext; /** * 存储异常和参数信息 */ private map<string,string> 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(3000); } 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() { } /** * 保存错误信息到文件中 * * @param ex * @return 返回文件名称,便于将文件传送到服务器 */ private string savecrashinfo2file(throwable ex) { stringbuffer sb = new stringbuffer(); for (map.entry<string, string> 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()); fos.close(); } return filename; } catch (exception e) { log.e(tag, "an error occured while writing file...", e); } return null; } }
activity管理类
package com.zly.www.basedemo.utils; import java.util.stack; import android.app.activity; import android.app.activitymanager; import android.content.context; /** * activity管理类:用于管理activity和退出程序 * created by zly on 2016/6/11. */ public class appmanager { // activity栈 private static stack<activity> activitystack; // 单例模式 private static appmanager instance; private appmanager() { } /** * 单一实例 */ public static appmanager getappmanager() { if (instance == null) { instance = new appmanager(); } return instance; } /** * 添加activity到堆栈 */ public void addactivity(activity activity) { if (activitystack == null) { activitystack = new stack<activity>(); } activitystack.add(activity); } /** * 获取当前activity(堆栈中最后一个压入的) */ public activity currentactivity() { activity activity = activitystack.lastelement(); return activity; } /** * 结束当前activity(堆栈中最后一个压入的) */ public void finishactivity() { activity activity = activitystack.lastelement(); finishactivity(activity); } /** * 结束指定的activity */ public void finishactivity(activity activity) { if (activity != null) { activitystack.remove(activity); activity.finish(); activity = null; } } /** * 结束指定类名的activity */ public void finishactivity(class<?> cls) { for (activity activity : activitystack) { if (activity.getclass().equals(cls)) { finishactivity(activity); break; } } } /** * 结束所有activity */ public void finishallactivity() { for (int i = 0; i < activitystack.size(); i++) { if (null != activitystack.get(i)) { activitystack.get(i).finish(); } } activitystack.clear(); } /** * 退出应用程序 */ public void appexit(context context) { try { finishallactivity(); //退出程序 android.os.process.killprocess(android.os.process.mypid()); system.exit(1); } catch (exception e) { } } }
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!