package cm.android.log; import android.os.Environment; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.nio.charset.Charset; import cm.android.log.MyLog.MyLogManager; import cm.android.log.MyLog.MyLogManager.Level; import cm.android.log.MyLog.MyLogManager.LogMode; import cm.android.util.EnvironmentUtil; import cm.android.util.MyFormatter; import cm.java.util.IoUtil; /** * android Log的Adapter类,打印调试信息。 */ @Deprecated public class MyLog { private MyLog() { } /** * 设置日志级别 */ public static void setLogLevel(Level level) { MyLogManager.getLogger().logLevel = level; } /** * 设置日志记录模式 */ public static void setLogMode(LogMode mode) { if (mode != null) { MyLogManager.getLogger().logMode = mode; } } /** * 初始化 */ public static void initialize(String traceTag) { MyLogManager.getLogger().init(traceTag); } /** * 释放 */ public static void release() { MyLogManager.getLogger().deInit(); } /** * 打印{@link Level#DEBUG}级别的日志 */ public static void d(String msg) { MyLogManager.getLogger().log(Level.DEBUG, msg); } // public void d(String msg) { // log(Level.DEBUG, msg); // } /** * 打印{@link Level#INFO}级别的日志 */ public static void i(String msg) { MyLogManager.getLogger().log(Level.INFO, msg); } /** * 打印{@link Level#ERROR}级别的日志 */ public static void e(String msg) { MyLogManager.getLogger().log(Level.ERROR, msg); } /** * 打印{@link Level#ERROR}级别的日志 */ public static void e(Throwable tr) { MyLogManager.getLogger().log(Level.ERROR, android.util.Log.getStackTraceString(tr)); } /** * 打印{@link Level#ERROR}级别的日志 */ public static void e(String msg, Throwable tr) { MyLogManager.getLogger().log( Level.ERROR, msg + System.getProperty("line.separator") + android.util.Log.getStackTraceString(tr)); } /** * 判断是否为DEBUG级别 */ public static boolean isDebug() { // 设置的level比debug小,则可以记录debug日志 return MyLogManager.getLogger().logLevel.getLevel() <= Level.DEBUG .getLevel(); } /** * 日志管理类 */ public static class MyLogManager { volatile String MY_TRACE = "MY_TRACE: "; // 可配参数 Level logLevel = Level.MAX; LogMode logMode = LogMode.LOGCAT; // logger private LogcatLogger logcatLogger = new LogcatLogger(); private FileLogger fileLogger = new FileLogger(logcatLogger); private MyLogManager() { } static MyLogManager getLogger() { return SingletonHolder.INSTANCE; } public String getMyTrace() { return MY_TRACE; } void log(Level level, String msg) { if (level.getLevel() < logLevel.getLevel()) { return; } // logcat logcatLogger.log(level, msg); if (isMode(LogMode.FILE)) { fileLogger.log(level, msg); } } void init(String traceTag) { MY_TRACE = traceTag + ": "; if (isMode(LogMode.FILE)) { fileLogger.initSdcardMode(); } String format = "MODE = %s,LEVEL = %s"; log(Level.INFO, String.format(format, logMode, logLevel)); } void deInit() { if (isMode(LogMode.FILE)) { fileLogger.releaseSdcardMode(); } } private boolean isMode(LogMode mode) { // return (MODE & mode) == mode; return logMode == mode; } /** * 日志记录模式 {@link #LOGCAT}和{@link #FILE} */ public static enum LogMode { /** * logcat方式输出 */ LOGCAT, /** * 日志写入到本地文件 */ FILE; private LogMode() { } } /** * 日志记录级别 */ public static enum Level { /** * DEBUG */ DEBUG("[DEBUG] - ", android.util.Log.DEBUG), /** * INFO */ INFO("[INFO] - ", android.util.Log.INFO), /** * ERROR */ ERROR("[ERROR] - ", android.util.Log.ERROR), /** * MAX,不记录日志 */ MAX("", Integer.MAX_VALUE); private String tag = null; private int level = 0; private Level(String tag, int level) { this.tag = tag; this.level = level; } public int getLevel() { return level; } public String getTag() { return tag; } } private static final class SingletonHolder { private static final MyLogManager INSTANCE = new MyLogManager(); } } } abstract class MyBaseLogger { private static String generateTag(StackTraceElement caller) { String tag = "[ %s:%s:%s():%d ]"; String callerFileName = caller.getFileName(); String fileName = callerFileName; // if (null != callerFileName) { // fileName = callerFileName.substring(0, // callerFileName.lastIndexOf('.')); // } tag = String.format(tag, Thread.currentThread().getName(), fileName, caller.getMethodName(), caller.getLineNumber()); return tag; } protected String getTag() { StringBuilder sb = new StringBuilder(); StackTraceElement[] sts = Thread.currentThread().getStackTrace(); if (sts == null) { return null; } for (StackTraceElement st : sts) { if (st.getClassName().equals(MyBaseLogger.class.getName())) { continue; } if (st.getClassName().equals(MyLogManager.class.getName())) { continue; } if (st.getClassName().equals(MyLog.class.getName())) { continue; } if (st.isNativeMethod()) { continue; } if (st.getClassName().equals(Thread.class.getName())) { continue; } if (st.getClassName().equals(this.getClass().getName())) { continue; } sb.append(generateTag(st)); return sb.toString(); } return null; } /** * 运行UT时打印一行信息 */ protected void printLine(String tag, String msg) { StringBuilder sb = new StringBuilder(); sb.append(tag); sb.append(" "); sb.append(msg); System.out.println(sb.toString()); } public abstract void log(Level level, String msg); } class LogcatLogger extends MyBaseLogger { @Override public void log(Level level, String msg) { String tag = getTag(); String msgStr = msg; // String tag = MyLogManager.MY_TRACE; // String msgStr = getTag() + " - " + msg; try { if (Level.DEBUG == level) { android.util.Log.d(tag, msgStr); } else if (Level.INFO == level) { android.util.Log.i(tag, msgStr); } else if (Level.ERROR == level) { android.util.Log.e(tag, msgStr); } } catch (Exception e) { printLine(tag, msgStr); } } } class FileLogger extends MyBaseLogger { private static final int BUFFER_SIZE = 1024 * 100; private static final String FILE_EXT = ".log"; private volatile boolean initSdcardSuccess = false; private File logFile; private BufferedOutputStream outputStream = null; private StringBuilder builder = new StringBuilder(); private LogcatLogger logcatLogger; public FileLogger(LogcatLogger logcatLogger) { this.logcatLogger = logcatLogger; } private String getName() { String fileNameFormat = "%s_%s.%s"; String fileName = String.format(fileNameFormat, MyLogManager.getLogger().getMyTrace(), getCurrDateStr(), FILE_EXT); return fileName; } public void initSdcardMode() { if (initSdcardSuccess) { return; } logFile = Environment.getExternalStorageDirectory(); if (!EnvironmentUtil.isExternalStorageWritable()) { logFile = null; } if (logFile == null) { return; } logFile = new File(logFile, getName()); boolean append = true; // 是否存在文件 if (!logFile.exists()) { IoUtil.createFile(logFile); append = false; } try { outputStream = new BufferedOutputStream(new FileOutputStream( logFile, append), BUFFER_SIZE); if (null == outputStream) { logcatLogger.log(Level.ERROR, "Open logfile failed!"); return; } initSdcardSuccess = true; } catch (Exception e) { logcatLogger.log(Level.ERROR, "Open logfile exception!"); e.printStackTrace(); } } public void releaseSdcardMode() { initSdcardSuccess = false; if (null != outputStream) { try { outputStream.flush(); outputStream.close(); outputStream = null; } catch (Exception e) { e.printStackTrace(); } } } private String getCurrDateStr() { return MyFormatter.formatDate("yyyyMMdd", System.currentTimeMillis()); } public synchronized void log(Level level, String msg) { if (!initSdcardSuccess) { logcatLogger.log(Level.ERROR, "Try open logfile."); initSdcardMode(); } if (null != outputStream) { String str = formatLogStr(level, MyLogManager.getLogger().getMyTrace(), msg); try { outputStream.write(str.getBytes(Charset.defaultCharset())); } catch (Exception e) { initSdcardSuccess = false; logcatLogger.log(Level.ERROR, android.util.Log.getStackTraceString(e)); e.printStackTrace(); } } } private String formatLogStr(Level level, String tag, String msg) { // 格式:[INFO] - YYYY-MM-DD HH:MM:SS.SSS :[tag] msg builder.setLength(0); builder.append(level.getTag()); builder.append( MyFormatter.formatDate("yyyy-MM-dd HH:mm:ss.SSS", System.currentTimeMillis())); builder.append(" : ["); builder.append(tag); builder.append("] "); builder.append(getTag()); builder.append(" - "); builder.append(msg); builder.append(System.getProperty("line.separator")); return builder.toString(); } }