Android程序异常捕捉并上传服务器

来源:互联网 发布:windows live id注册 编辑:程序博客网 时间:2024/05/21 14:48
Android市场品牌多样,一些比较强势的公司都定制了自己的系统,所以在开发过程中就算很严密的测试还是会遇到一些漏网之鱼,所以开发应用的全局异常    捕捉处理是一项重要的工作,以便我们及时发现问题并处理。其实安卓默认了一个UncaughtException处理类,我们只需继承该类并收集信息及时处理。
/** * 异常处理类,继承UncaughtException处理类 * * Created by wk */public class MyCrashHandler implements UncaughtExceptionHandler {    private UncaughtExceptionHandler crashHandler;    private Context mContext;    // CrashHandler实例    private static MyCrashHandler INSTANCE = new MyCrashHandler();    /**     * 单例模式,保证只有一个CrashHandler实例     */    private MyCrashHandler() {    }    public static MyCrashHandler getInstance() {        return INSTANCE;    }    /**     * 初始化     *     * @param context     */    public void init(Context context) {        mContext = context;        // 获取UncaughtException处理器        crashHandler = Thread.getDefaultUncaughtExceptionHandler();        Thread.setDefaultUncaughtExceptionHandler(this);    }    /**     * 重写方法,异常发生时调用     */    @Override    public void uncaughtException(Thread thread, Throwable ex) {        if (!dealException(ex) && crashHandler != null) {            crashHandler.uncaughtException(thread, ex);        }        //此处还可以进行一些异常后续处理,如杀死进程,finish页面的操作    }    /**     * 收集设备参数信息     *     * @param context     */    public Map<String, String> collectDeviceInfo(Context context) {        Map<String, String> infos = new HashMap<String, String>();        try {            PackageManager pManager = context.getPackageManager();            PackageInfo pInfo = pManager.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);            if (pInfo != null) {                String versionName = "";                if (versionName == null) {                    versionName = null;                } else {                    versionName = pInfo.versionName;                }                String versionCode = pInfo.versionCode + "";                infos.put("versionName", versionName);                infos.put("versionCode", versionCode);            }        } catch (NameNotFoundException e) {        }        //获取手机的信息        Field[] fields = Build.class.getDeclaredFields();        for (Field field : fields) {            try {                //跳过安全检查,Filed是private的话会抛出异常,以防万一                field.setAccessible(true);                infos.put(field.getName(), field.get(null).toString());            } catch (Exception e) {            }        }        return infos;    }    /**     * 保存错误信息到文件中     *     * @param ex     * @return 返回文件名称, 便于将文件传送到服务器     */    public void saveCrashInfo2File(Throwable ex, Map<String, String> infos) {        StringBuffer sb = new StringBuffer();        //遍历文件        for (Map.Entry<String, String> entry : infos.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 = DateUtil.long2string(timestamp, DateUtil.YYYY_MM_DD_HH_MM);            String fileName = "crash-" + time + "-" + timestamp + ".txt";            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {                //保存路径                String path = FileUtils.getInstance().getSDPATHWork() + "crash/";                File dir = new File(path);                if (!dir.exists()) {                    dir.mkdirs();                }                FileOutputStream fos = new FileOutputStream(path + fileName);                fos.write(sb.toString().getBytes());                // 发送给开发人员,上传                postReport(fileName, path + fileName);                fos.close();            }        } catch (Exception e) {        }    }    /**     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.     *     * @param ex     * @return true:如果处理了该异常信息;否则返回false.     */    private boolean dealException(Throwable ex) {        if (ex == null) {            return false;        }        // 使用Toast来显示异常信息        new Thread() {            @Override            public void run() {                Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出", Toast.LENGTH_LONG).show();            }        }.start();        // 收集设备参数信息        Map<String, String> infos = collectDeviceInfo(mContext);        // 保存日志文件        saveCrashInfo2File(ex, infos);        return true;    }    // 使用HTTP Post 发送错误报告到服务器    // 在上传的时候还可以将该app的version,该手机的机型等信息一并发送的服务器,    // Android的兼容性众所周知,所以可能错误不是每个手机都会报错,还是有针对性的去debug比较好    private void postReport(String fileName, String resFile) {    }}
该类中收集信息文件的命名可根据自己的需要进行修改,上传的方法也根据自己对应服务器的路径进行操作,此处省略。在application类中初始化全局异常捕捉实例即可。
/** * Created by wk  */public class MyApplication extends Application {    @Override    public void onCreate() {        super.onCreate();        //初始化异常处理对象        MyCrashHandler crashHandler = MyCrashHandler.getInstance();        crashHandler.init(getApplicationContext());    }}
1 0