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

来源:互联网 发布:js截图插件 编辑:程序博客网 时间:2024/05/29 03:17

最近写的项目需要自己写全局的异常捕捉,所以百度了很多解决方案,发现出现各种问题,好不容易找到一些比较靠谱的方案,但是却发现出现了一个让我无语的问题——日志打印输出三次。于是又开始去寻找答案,发现并没有相关的解决。好嘛,看来还是要自己搞了。

发生该现象的基本原因就是: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<Activity> activitys = new LinkedList<Activity>();    private List<Service> services = new LinkedList<Service>();    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<Activity> 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<Activity> iterator = activitys.listIterator();        while (iterator.hasNext()) {            Activity activity = iterator.next();            if (activity != null) {                activity.finish();            }        }    }    /**     *      * TODO 关闭所有的Service     */    private void closeServices() {        ListIterator<Service> 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菜鸟一枚,并非大牛,可能部分代码不尽如人意,希望各位大大可以予以指出,我会虚心接受并积极改正,谢谢大家!

2 0
原创粉丝点击