美文网首页
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日志

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