美文网首页
android保存log和crash日志

android保存log和crash日志

作者: 金卡戴珊ugly | 来源:发表于2019-08-12 15:13 被阅读0次

1,公司做第三方公司投影仪适配,无法使用adb所以保存日志到sd卡。方便调错。
LogSaver.java

public class LogSaver {
    private static LogSaver INSTANCE = null;
    private static String PATH_LOGCAT;
    private LogDumper mLogDumper = null;
    private int mPId;
    public void init(Context context) {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {// 优先保存到SD卡中
            PATH_LOGCAT = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "log";
        } else {// 如果SD卡不存在,就保存到本应用的目录下
            PATH_LOGCAT = context.getFilesDir().getAbsolutePath() + File.separator + "log";
        }
        File file = new File(PATH_LOGCAT);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    public static LogSaver getInstance(Context context) {
        if (INSTANCE == null) {
            INSTANCE = new LogSaver(context);
        }
        return INSTANCE;
    }

    private LogSaver(Context context) {
        init(context);
        mPId = android.os.Process.myPid();
    }

    public void start() {
        if (mLogDumper == null) {
            mLogDumper = new LogDumper(String.valueOf(mPId), PATH_LOGCAT);
        }
        Log.i("path", PATH_LOGCAT);/// storage/sdcard0/miniGPS
        mLogDumper.start();
    }
    public void stop() {
        if (mLogDumper != null) {
            mLogDumper.stopLogs();
            mLogDumper = null;
        }
    }
    private class LogDumper extends Thread {
        private Process logcatProc;
        private BufferedReader mReader = null;
        private boolean mRunning = true;
        String cmds = null;
        private String mPID;
        private FileOutputStream out = null;

        public LogDumper(String pid, String dir) {
            mPID = pid;
            try {
                out = new FileOutputStream(new File(dir, "GPS-" + new MyDate().getFileName() + ".log"));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            /**
             * 日志等级:*:v , *:d , *:w , *:e , *:f , *:s
             * 显示当前mPID程序的 E和W等级的日志.
             */
            cmds = "logcat *:e *:i *:d *:w *:v *:d | grep \"(" + mPID + ")\"";// 会打印i,e,w,不会打印d
        }

        public void stopLogs() {
            mRunning = false;
        }

        @Override
        public void run() {
            try {
                logcatProc = Runtime.getRuntime().exec(cmds);
                mReader = new BufferedReader(new InputStreamReader(logcatProc.getInputStream()), 1024);
                String line = null;
                while (mRunning && (line = mReader.readLine()) != null) {
                    if (!mRunning) {
                        break;
                    }
                    if (line.length() == 0) {
                        continue;
                    }
                    if (out != null && line.contains(mPID)) {
                        out.write((new MyDate().getDateEN() + "  " + line + "\n").getBytes());
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (logcatProc != null) {
                    logcatProc.destroy();
                    logcatProc = null;
                }
                if (mReader != null) {
                    try {
                        mReader.close();
                        mReader = null;
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    out = null;
                }
            }
        }
    }

    class MyDate {
        public String getFileName() {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            String date = format.format(new Date(System.currentTimeMillis()));
            return date;// 2012年10月03日 23:41:31
        }

        public String getDateEN() {
            SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String date1 = format1.format(new Date(System.currentTimeMillis()));
            return date1;// 2012-10-03 23:41:31
        }
    }
}

使用需要初始化

LogSaver.getInstance(this).start();

报错日志打印更直观记录crash日志
CrashLogHandlerUtils.java

public class CrashLogHandlerUtils implements UncaughtExceptionHandler {

    private static CrashLogHandlerUtils mSelf;

    // 系统默认的UncaughtException处理类
    private UncaughtExceptionHandler mDefaultHandler;

    // 程序的Context对象
    private Context mContext;

    //保存log的文件夹
    private File mSaveDir;

    //在log上面添加的额外信息
    private String mTopMsg;

    //在log下面添加的额外信息
    private String mBottomMsg;

    //在保存新log的同时是否删除7天前的log
    private boolean mDeleteOld;

    // 用于格式化日期,作为日志文件名的一部分
    private DateFormat mFormatter = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");

    private CrashLogHandlerUtils(Application application) {
        mContext = application;
        // 设置log默认保存目录
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            mSaveDir = application.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
        }
        // 设置默认的在log上面添加的额外信息
        setDefaultsTopMsg();
        // 设置默认的在log下面添加的额外信息
        setDefaultsBottomMsg();
    }

    /**
     * @param application 运行环境
     * @return 返回实例
     */
    public static synchronized CrashLogHandlerUtils getInstance(Application application) {
        if (mSelf == null) {
            mSelf = new CrashLogHandlerUtils(application);
        }
        return mSelf;
    }

    /**
     * 设置保存log的文件夹,默认为{@link Environment#DIRECTORY_DOCUMENTS}
     * @param saveDir 保存log的文件夹
     * @return self
     */
    public CrashLogHandlerUtils setSavePath(File saveDir) {
        mSelf.mSaveDir = saveDir;
        return mSelf;
    }

    /**
     * 设置在log上面添加的额外信息
     * @param topMsg 添加在log上面添加的额外信息
     * @return self
     */
    public CrashLogHandlerUtils setLogTopMessage(String topMsg) {
        mSelf.mTopMsg = topMsg;
        return mSelf;
    }

    /**
     * 设置在log下面添加的额外信息
     * @param bottomMsg 添加在log下面添加的额外信息
     * @return self
     */
    public CrashLogHandlerUtils setLogBottomMessage(String bottomMsg) {
        mSelf.mBottomMsg = bottomMsg;
        return mSelf;
    }

    /**
     * 设置在保存新log的同时是否删除7天前的log, 默认为{@code false}
     * @param deleteOldLog 是否删除
     * @return self
     */
    public CrashLogHandlerUtils setDeleteOldLog(boolean deleteOldLog) {
        mSelf.mDeleteOld = deleteOldLog;
        return mSelf;
    }

    /**
     * 启动异常退出log捕捉
     */
    public void start() {
        // 获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        // 设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex) && mDefaultHandler != null) {
            mDefaultHandler.uncaughtException(thread, ex);
        }
    }

    /**
     * @param ex 异常
     * @return @code false,因为本工具只保存异常日志,不捕获异常,所以只返回@code false
     */
    private boolean handleException(Throwable ex) {
        if (ex != null) {
            saveCrashInfo2File(ex);
        }
        return false;
    }

    /**
     * 保存错误信息到文件中
     * @param ex Crash异常
     * @return 是否保存成功
     */
    private boolean saveCrashInfo2File(Throwable ex) {
        Calendar calendar = Calendar.getInstance();
        StringBuffer sb = new StringBuffer();
        sb.append(mTopMsg);
        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);
        sb.append(mBottomMsg);
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            File dir = mSaveDir;
            if (!dir.exists()) {
                dir.mkdirs();
            }
            FileWriter fWriter = null;
            try {
                fWriter = new FileWriter(mSaveDir + "/" + getFileNameByCalendar(calendar), true);
                fWriter.write(sb.toString());
                fWriter.flush();
                fWriter.close();
                if (mDeleteOld) {
                    deleteOldFile(calendar);
                }
                return true;
            } catch (IOException e) {
                e.printStackTrace();
                if (fWriter != null) {
                    try {
                        fWriter.flush();
                        fWriter.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        }
        return false;
    }

    /**
     * 设置默认的在log上面添加的额外信息
     */
    private void setDefaultsTopMsg() {
        StringBuffer sb = new StringBuffer();
        Calendar calendar = Calendar.getInstance();
        Date date = new Date(calendar.getTimeInMillis());
        long timestamp = calendar.getTimeInMillis();
        String time = mFormatter.format(date);
        sb.append("--------本次错误开始--------\n");
        sb.append(time).append("_").append(timestamp).append("\n");
        try {
            PackageManager pm = mContext.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                sb.append("versionName:").append(versionName).append("\n");
                sb.append("versionCode:").append(versionCode).append("\n");
            }
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        mTopMsg = sb.toString();
    }

    /**
     * 设置默认的在log下面添加的额外信息
     */
    private void setDefaultsBottomMsg() {
        StringBuffer sb = new StringBuffer();
        sb.append("--------本次错误结束---------").append("\n\n");
        mBottomMsg = sb.toString();
    }

    /**
     * 删除给定日期的七天(含)前的及以后的log
     * @param todayCalendar 所以日期
     */
    private void deleteOldFile(Calendar todayCalendar) {
        File[] files = mSaveDir.listFiles();
        if (files != null && files.length > 0) {
            for (File file : files) {
                Calendar oldCalendar = (Calendar) todayCalendar.clone();
                oldCalendar.set(Calendar.DAY_OF_MONTH, oldCalendar.get(Calendar.DAY_OF_MONTH) - 1);
                if (file.isFile() && file.exists() && !file.getName().equals(getFileNameByCalendar(todayCalendar))
                        && !file.getName().equals(getFileNameByCalendar(getCalendarByCorrection(todayCalendar, -1)))
                        && !file.getName().equals(getFileNameByCalendar(getCalendarByCorrection(todayCalendar, -2)))
                        && !file.getName().equals(getFileNameByCalendar(getCalendarByCorrection(todayCalendar, -3)))
                        && !file.getName().equals(getFileNameByCalendar(getCalendarByCorrection(todayCalendar, -4)))
                        && !file.getName().equals(getFileNameByCalendar(getCalendarByCorrection(todayCalendar, -5)))
                        && !file.getName().equals(getFileNameByCalendar(getCalendarByCorrection(todayCalendar, -6)))) {
                    try {
                        file.delete();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * 获取所给日期的修正后的日期
     * @param calendar 原始日期
     * @param correctionDay 修正值,单位为天
     * @return 修正后的日期
     */
    private Calendar getCalendarByCorrection(Calendar calendar, int correctionDay) {
        Calendar oldCalendar = (Calendar) calendar.clone();
        oldCalendar.set(Calendar.DAY_OF_MONTH, oldCalendar.get(Calendar.DAY_OF_MONTH) + correctionDay);
        return oldCalendar;
    }

    /**
     * 根据日期获取文件名
     * @param calendar 日期
     * @return 文件名
     */
    private String getFileNameByCalendar(Calendar calendar) {
        if (calendar == null) {
            return null;
        }
        String fileName = "crash_log" + "_" + mContext.getResources().getString(R.string.app_name) + ".txt";
        return fileName;
    }
}

初始化:

CrashLogHandlerUtils.getInstance(this).setSavePath(Environment.getExternalStorageDirectory()).start();

相关文章

  • android保存log和crash日志

    1,公司做第三方公司投影仪适配,无法使用adb所以保存日志到sd卡。方便调错。LogSaver.java 使用需要...

  • mysql之日志系统:SQL更新语句逻辑

    mysql的2个重要日志:物理日志redo log和逻辑日志 binlog。redo log: 保证crash-s...

  • crash-log看什么

    获取crash-log:将手机连接到电脑上,看android studio下的error日志 崩溃情况 1.手机系...

  • iOS Crash 大解析

    iOS crash / 崩溃/ 异常 /捕获 1 崩溃日志(crash log) Xcode中 查看崩溃信息 手...

  • iOS解析crash日志

    Update Log: 2017.8.24: 初版 一.获取.crash文件 真机连接电脑.导出.crash日志文...

  • Innodb日志机制

    1.1. Log & CheckpointInnodb的事务日志是指Redo log,简称Log,保存在日志文件...

  • Android日志打印工具-android-ueueo-log

    android-ueueo-log android-ueueo-log是Android日志输出工具,对输出的日志信...

  • iOS Crash文件解析

    一.找到.app文件和.app.dSYM文件和导出crash log日志 在桌面创建一个crash文件夹,然后Xc...

  • iOS Crash日志获取和上传

    漫谈iOS Crash收集框架-程序媛念茜 iOS摇一摇在屏幕上实时显示log和crash日志 使用NSSetUn...

  • 解析iOS崩溃日志

    在常规的的log日志下能分析很多crash,那么问题来了。分发测试或者上线了的包怎么抓取和分析crash。常规的解...

网友评论

      本文标题:android保存log和crash日志

      本文链接:https://www.haomeiwen.com/subject/qrjujctx.html