Android全局异常捕获,解决日志打印三次的BUG

【Android全局异常捕获,解决日志打印三次的BUG】最近写的项目需要自己写全局的异常捕捉,所以百度了很多解决方案,发现出现各种问题,好不容易找到一些比较靠谱的方案,但是却发现出现了一个让我无语的问题——日志打印输出三次。于是又开始去寻找答案,发现并没有相关的解决。好嘛,看来还是要自己搞了。
发生该现象的基本原因就是:Application没有完全退出,导致同一个异常多次执行,于是出现了同一个异常打印多次的问题
【解决方案】

  • 处理全局异常的Handler:CrashHandler.java,代码如下:
public class CrashHandler implements UncaughtExceptionHandler { private static CrashHandler instance; private UncaughtExceptionHandler mDefaultHandler; public void init(Context ctx) { Thread.setDefaultUncaughtExceptionHandler(this); mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); // 获取系统默认的UncaughtException处理器public static CrashHandler getInstance() { if (instance == null) { instance = new CrashHandler(); } return instance; }/** * 核心方法,当程序crash 会回调此方法, Throwable中存放这错误日志 */ @Override public synchronized void uncaughtException(Thread arg0, Throwable arg1) { if (mDefaultHandler != null && !handleException(arg1)) { // 如果自定义的没有处理则让系统默认的异常处理器来处理 mDefaultHandler.uncaughtException(arg0, arg1); } else { // 退出程序 try { Thread.sleep(3000); // 如果处理了,让程序继续运行3秒再退出,保证文件保存并上传到服务器 } catch (InterruptedException e) { e.printStackTrace(); } Myapplication.getApplication().closeApplication(); //完全退出Application //如果使用如下方法退出程序,将会发生日志打印三次的BUG //android.os.Process.killProcess(android.os.Process.myPid()); //System.exit(1); } }private boolean handleException(Throwable arg1) { String logPath; if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { logPath = Environment.getExternalStorageDirectory() .getAbsolutePath() + File.separator + File.separator + "log"; File file = new File(logPath); if (!file.exists()) { file.mkdirs(); } try { FileWriter fw = new FileWriter(logPath + File.separator + CommonUtil.getStrTime() + ".log", false); StringBuffer sb = new StringBuffer(); sb.append("/*************************************************/\n"); sb.append(new Date() + "\n"); // 错误信息 // 这里还可以加上当前的系统版本,机型型号 等等信息 StackTraceElement[] stackTrace = arg1.getStackTrace(); sb.append("错误信息:" + arg1.getMessage() + "\n"); for (int i = 0; i < stackTrace.length; i++) { String info = "文件:" + stackTrace[i].getFileName() + "类:" + stackTrace[i].getClassName() + "方法:" + stackTrace[i].getMethodName() + "行号:" + stackTrace[i].getLineNumber() + "\n"; sb.append(info); } sb.append("/*************************************************/\n"); fw.write(sb.toString()); fw.close(); // 上传错误信息到服务器 uploadToServer(sb); } catch (IOException e) { Log.e("crash handler", "load file failed...", e.getCause()); } } return true; }private void uploadToServer(StringBuffer sb) { //执行上传操作,错误信息为:sb.toString(); }}

  • Handler的初始化以及MyApplication的编写:MyApplication.java
public class Myapplication extends Application { private List activitys = new LinkedList(); private List services = new LinkedList(); private static int mTid; private static Myapplication mApplication; private CrashHandler crashHandler; @Override public void onCreate() { super.onCreate(); mApplication = this; mTid = android.os.Process.myTid(); crashHandler = CrashHandler.getInstance(); crashHandler.init(getApplicationContext()); }/** * * TODO 获取活动队列 */ public List getActivitys() { return activitys; }/** * * TODO 添加Activity */ public void addActivity(Activity activity) { activitys.add(activity); }/** * * TODO 移除Activity */ public void removeActivity(Activity activity) { activitys.remove(activity); }/** * * TODO 添加服务 */ public void addService(Service service) { services.add(service); }/** * * TODO 移除Service */ public void removeService(Service service) { services.remove(service); }/** * * TODO 关闭程序 */ public void closeApplication() { closeActivitys(); closeServices(); android.os.Process.killProcess(android.os.Process.myPid()); }/** * * TODO 关闭所有的Activity */ public void closeActivitys() { ListIterator iterator = activitys.listIterator(); while (iterator.hasNext()) { Activity activity = iterator.next(); if (activity != null) { activity.finish(); } } }/** * * TODO 关闭所有的Service */ private void closeServices() { ListIterator iterator = services.listIterator(); while (iterator.hasNext()) { Service service = iterator.next(); if (service != null) { stopService(new Intent(this, service.getClass())); } } }/** * * TODO 获取Application */ public static Myapplication getApplication() { return mApplication; }/** * * TODO 获取主线程PID */ public static int getmTid() { return mTid; }}

  • BaseActivity的编写:BaseActivity.java
public class BaseActivity extends Activity { protected BaseActivity mActivity; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 保存生命周期的完整性 ((Myapplication) getApplication()).addActivity(this); mActivity = this; }@Override protected void onDestroy() { super.onDestroy(); ((Myapplication) getApplication()).removeActivity(this); } }

总结 以上代码仅供参考,可能有更好的解决方法,欢迎大家给我留言。本人Android菜鸟一枚,并非大牛,可能部分代码不尽如人意,希望各位大大可以予以指出,我会虚心接受并积极改正,谢谢大家!

    推荐阅读