将log保存到本地

来源:互联网 发布:武装党卫军 知乎 编辑:程序博客网 时间:2024/06/01 07:33

app在现场测试,发生crash时无法从logcat找到原因,如能将发生错误时的log记录下来,对debug非常有利.
关键接口:Thread.UncaughtExceptionHandler用来捕获运行时未被程序捕获的异常
关键方法
@Override
public void uncaughtException(Thread thread, Throwable ex) {
//错误发生后要执行的操作,如保存错误报告
//这个是最关键的函数,当程序中有未被捕获的异常,系统将会自动调用#uncaughtException方法
//thread为出现未捕获异常的线程,ex为未捕获的异常,有了这个ex,我们就可以得到异常信息。报告
}
通过Thread.setDefaultUncaughtExceptionHandler()方法将异常处理类设置到线程上即可.

下面是收集log的工具类的范例代码:

public class LogCollectionUtil implements UncaughtExceptionHandler {    private Context mContext;    private static final String SDCARD_PATH = Environment            .getExternalStorageDirectory().toString();    // 系统默认的异常处理(默认情况下系统会终止当前的异常程序)    private UncaughtExceptionHandler mUncaughtExceptionHandler;    private CopyOfLogCollectionUtil2() {    };    private static CopyOfLogCollectionUtil2 instance = new CopyOfLogCollectionUtil2();    public static CopyOfLogCollectionUtil2 getLogCollectionUtil() {        return instance;    }    /**     * 初始化,注册Context对象, 获取系统默认的UncaughtException处理器, 设置该CrashHandler为程序的默认处理器     *      * @param context     */    public void setCrashHandler(Context context) {        mContext = context;        Thread.setDefaultUncaughtExceptionHandler(this);    }    /**     * 当uncaughtException发生时会转入该函数处理     */    @Override    public void uncaughtException(Thread thread, Throwable ex) {        dumpExceptionToSDCard(mContext, ex);        showToast(mContext, "我挂了...");        try {            Thread.sleep(3000);        } catch (InterruptedException e) {            e.printStackTrace();        }        // 如果系统提供了默认异常处理器,交给系统结束我们的程序,否则自己结束自己        if (mUncaughtExceptionHandler != null) {            mUncaughtExceptionHandler.uncaughtException(thread, ex);        } else {            android.os.Process.killProcess(android.os.Process.myPid());            System.exit(1);        }    }    /**     * save exception info to sd     *      * @param context     * @param ex     * @return     */    private void dumpExceptionToSDCard(Context context, Throwable ex) {        String fileName = createFile();        try {            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(                    fileName)));            dumpPhoneInfo(pw);            pw.println();            dumpCrashInfo(ex, pw);            pw.close();        } catch (Exception e) {            Log.e("dd", "dump crash info failed");        }    }    /**     * create file in SDCard     *      * @return     */    private String createFile() {        String fileName;        File dir = null;        if (Environment.getExternalStorageState().equals(                Environment.MEDIA_MOUNTED)) {            dir = new File(SDCARD_PATH + File.separator + "crash" + File.separator);            if (!dir.exists()) {                dir.mkdir();            }        }        return fileName = dir.toString() + File.separator                + parseTime(System.currentTimeMillis()) + ".log";    }    /**     * collect device info     *      * @param pw     * @throws NameNotFoundException     */    private void dumpPhoneInfo(PrintWriter pw) throws NameNotFoundException {        PackageManager pm = mContext.getPackageManager();        PackageInfo packageInfo = pm.getPackageInfo(mContext.getPackageName(),                PackageManager.GET_ACTIVITIES);        pw.println("App version: " + packageInfo.versionName + '_'                + packageInfo.versionCode);        pw.println("OS version: " + Build.VERSION.RELEASE + '_'                + Build.VERSION.SDK_INT);        // The manufacturer of the product/hardware.        pw.println("Vendor: " + Build.MANUFACTURER);        pw.println("Model: " + Build.MODEL);        pw.println("Product: " + Build.PRODUCT);        pw.println("Brand: " + Build.BRAND);        pw.println("Display: " + Build.DISPLAY);        pw.println("Device: " + Build.DEVICE);        pw.println("CPU abi: " + Build.CPU_ABI);        pw.println("Fingerprint: " + Build.FINGERPRINT);    }    /**     * collect log info     *      * @param throwable     * @param pw     */    private void dumpCrashInfo(Throwable throwable, PrintWriter pw) {        throwable.printStackTrace(pw);    }    /**     * format time     *      * @param milliseconds     * @return     */    private String parseTime(long milliseconds) {        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        format.setTimeZone(TimeZone.getDefault());        String times = format.format(new Date(milliseconds));        return times;    }    /**     * give user tips     *      * @param context     * @param msg     */    private void showToast(final Context context, final String msg) {        new Thread(new Runnable() {            @Override            public void run() {                Looper.prepare();                Toast.makeText(context, msg, Toast.LENGTH_LONG).show();                Looper.loop();            }        }).start();    }}

使用时将以上代码放到你的包里,将如下代码添加到application类的onCreate()方法里即可使用(放在activity的onCreate()方法里也是可以的,这样只能捕获这个activity的crash,定义在application类里可以捕获app所有线程的异常.).
LogCollectionUtil mLogCollection=LogCollectionUtil.getLogCollectionUtil();
mLogCollection.setCrashHandler(this);
发生crash后,在你手机里的crash文件夹下寻找log.

0 0
原创粉丝点击