提交 f3016188 编写于 作者: B Blankj

see 04/10 log

上级 50173f22
......@@ -7,6 +7,7 @@ import android.os.Build;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresPermission;
import android.util.Log;
import java.io.BufferedWriter;
import java.io.File;
......@@ -18,8 +19,10 @@ import java.lang.Thread.UncaughtExceptionHandler;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
......@@ -38,8 +41,6 @@ public final class CrashUtils {
private static String versionName;
private static int versionCode;
private static ExecutorService sExecutor;
private static final String FILE_SEP = System.getProperty("file.separator");
@SuppressLint("SimpleDateFormat")
private static final Format FORMAT = new SimpleDateFormat("MM-dd HH-mm-ss");
......@@ -105,30 +106,11 @@ public final class CrashUtils {
Date now = new Date(System.currentTimeMillis());
String fileName = FORMAT.format(now) + ".txt";
final String fullPath = (dir == null ? defaultDir : dir) + fileName;
if (!createOrExistsFile(fullPath)) return;
if (sExecutor == null) {
sExecutor = Executors.newSingleThreadExecutor();
if (createOrExistsFile(fullPath)) {
input2File(crashInfo, fullPath);
} else {
Log.e("CrashUtils", "create " + fullPath + " failed!");
}
sExecutor.execute(new Runnable() {
@Override
public void run() {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(fullPath, false));
bw.write(crashInfo);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bw != null) {
try {
bw.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
});
if (sOnCrashListener != null) {
sOnCrashListener.onCrash(crashInfo, e);
......@@ -229,6 +211,39 @@ public final class CrashUtils {
Thread.setDefaultUncaughtExceptionHandler(UNCAUGHT_EXCEPTION_HANDLER);
}
private static void input2File(final String input, final String filePath) {
Future<Boolean> submit = Executors.newSingleThreadExecutor().submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(filePath, true));
bw.write(input);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
try {
if (bw != null) {
bw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
try {
if (submit.get()) return;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Log.e("CrashUtils", "write crash info to " + filePath + " failed!");
}
private static boolean createOrExistsFile(final String filePath) {
File file = new File(filePath);
if (file.exists()) return file.isFile();
......
......@@ -85,23 +85,7 @@ public final class LogUtils {
private static final String ARGS = "args";
private static final String PLACEHOLDER = " ";
private static final Config CONFIG = new Config();
private static ExecutorService sExecutor;
private static String sDefaultDir;// The default storage directory of log.
private static String sDir; // The storage directory of log.
private static String sFilePrefix = "util";// The file prefix of log.
private static boolean sLogSwitch = true; // The switch of log.
private static boolean sLog2ConsoleSwitch = true; // The logcat's switch of log.
private static String sGlobalTag = null; // The global tag of log.
private static boolean sTagIsSpace = true; // The global tag is space.
private static boolean sLogHeadSwitch = true; // The head's switch of log.
private static boolean sLog2FileSwitch = false; // The file's switch of log.
private static boolean sLogBorderSwitch = true; // The border's switch of log.
private static boolean sSingleTagSwitch = true; // The single tag of log.
private static int sConsoleFilter = V; // The console's filter of log.
private static int sFileFilter = V; // The file's filter of log.
private static int sStackDeep = 1; // The stack's deep of log.
private LogUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
......@@ -112,7 +96,7 @@ public final class LogUtils {
}
public static void v(final Object... contents) {
log(V, sGlobalTag, contents);
log(V, CONFIG.mGlobalTag, contents);
}
public static void vTag(final String tag, final Object... contents) {
......@@ -120,7 +104,7 @@ public final class LogUtils {
}
public static void d(final Object... contents) {
log(D, sGlobalTag, contents);
log(D, CONFIG.mGlobalTag, contents);
}
public static void dTag(final String tag, final Object... contents) {
......@@ -128,7 +112,7 @@ public final class LogUtils {
}
public static void i(final Object... contents) {
log(I, sGlobalTag, contents);
log(I, CONFIG.mGlobalTag, contents);
}
public static void iTag(final String tag, final Object... contents) {
......@@ -136,7 +120,7 @@ public final class LogUtils {
}
public static void w(final Object... contents) {
log(W, sGlobalTag, contents);
log(W, CONFIG.mGlobalTag, contents);
}
public static void wTag(final String tag, final Object... contents) {
......@@ -144,7 +128,7 @@ public final class LogUtils {
}
public static void e(final Object... contents) {
log(E, sGlobalTag, contents);
log(E, CONFIG.mGlobalTag, contents);
}
public static void eTag(final String tag, final Object... contents) {
......@@ -152,7 +136,7 @@ public final class LogUtils {
}
public static void a(final Object... contents) {
log(A, sGlobalTag, contents);
log(A, CONFIG.mGlobalTag, contents);
}
public static void aTag(final String tag, final Object... contents) {
......@@ -160,11 +144,11 @@ public final class LogUtils {
}
public static void file(final Object content) {
log(FILE | D, sGlobalTag, content);
log(FILE | D, CONFIG.mGlobalTag, content);
}
public static void file(@TYPE final int type, final Object content) {
log(FILE | type, sGlobalTag, content);
log(FILE | type, CONFIG.mGlobalTag, content);
}
public static void file(final String tag, final Object content) {
......@@ -176,11 +160,11 @@ public final class LogUtils {
}
public static void json(final String content) {
log(JSON | D, sGlobalTag, content);
log(JSON | D, CONFIG.mGlobalTag, content);
}
public static void json(@TYPE final int type, final String content) {
log(JSON | type, sGlobalTag, content);
log(JSON | type, CONFIG.mGlobalTag, content);
}
public static void json(final String tag, final String content) {
......@@ -192,11 +176,11 @@ public final class LogUtils {
}
public static void xml(final String content) {
log(XML | D, sGlobalTag, content);
log(XML | D, CONFIG.mGlobalTag, content);
}
public static void xml(@TYPE final int type, final String content) {
log(XML | type, sGlobalTag, content);
log(XML | type, CONFIG.mGlobalTag, content);
}
public static void xml(final String tag, final String content) {
......@@ -208,31 +192,31 @@ public final class LogUtils {
}
private static void log(final int type, final String tag, final Object... contents) {
if (!sLogSwitch || (!sLog2ConsoleSwitch && !sLog2FileSwitch)) return;
if (!CONFIG.mLogSwitch || (!CONFIG.mLog2ConsoleSwitch && !CONFIG.mLog2FileSwitch)) return;
int type_low = type & 0x0f, type_high = type & 0xf0;
if (type_low < sConsoleFilter && type_low < sFileFilter) return;
if (type_low < CONFIG.mConsoleFilter && type_low < CONFIG.mFileFilter) return;
final TagHead tagHead = processTagAndHead(tag);
String body = processBody(type_high, contents);
if (sLog2ConsoleSwitch && type_low >= sConsoleFilter && type_high != FILE) {
if (CONFIG.mLog2ConsoleSwitch && type_low >= CONFIG.mConsoleFilter && type_high != FILE) {
print2Console(type_low, tagHead.tag, tagHead.consoleHead, body);
}
if ((sLog2FileSwitch || type_high == FILE) && type_low >= sFileFilter) {
if ((CONFIG.mLog2FileSwitch || type_high == FILE) && type_low >= CONFIG.mFileFilter) {
print2File(type_low, tagHead.tag, tagHead.fileHead + body);
}
}
private static TagHead processTagAndHead(String tag) {
if (!sTagIsSpace && !sLogHeadSwitch) {
tag = sGlobalTag;
if (!CONFIG.mTagIsSpace && !CONFIG.mLogHeadSwitch) {
tag = CONFIG.mGlobalTag;
} else {
final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
StackTraceElement targetElement = stackTrace[3];
final String fileName = getFileName(targetElement);
if (sTagIsSpace && isSpace(tag)) {
if (CONFIG.mTagIsSpace && isSpace(tag)) {
int index = fileName.indexOf('.');// Use proguard may not find '.'.
tag = index == -1 ? fileName : fileName.substring(0, index);
}
if (sLogHeadSwitch) {
if (CONFIG.mLogHeadSwitch) {
String tName = Thread.currentThread().getName();
final String head = new Formatter()
.format("%s, %s.%s(%s:%d)",
......@@ -243,11 +227,11 @@ public final class LogUtils {
targetElement.getLineNumber())
.toString();
final String fileHead = " [" + head + "]: ";
if (sStackDeep <= 1) {
if (CONFIG.mStackDeep <= 1) {
return new TagHead(tag, new String[]{head}, fileHead);
} else {
final String[] consoleHead =
new String[Math.min(sStackDeep, stackTrace.length - 3)];
new String[Math.min(CONFIG.mStackDeep, stackTrace.length - 3)];
consoleHead[0] = head;
int spaceLen = tName.length() + 2;
String space = new Formatter().format("%" + spaceLen + "s", "").toString();
......@@ -347,10 +331,10 @@ public final class LogUtils {
final String tag,
final String[] head,
final String msg) {
if (sSingleTagSwitch) {
if (CONFIG.mSingleTagSwitch) {
StringBuilder sb = new StringBuilder();
sb.append(PLACEHOLDER).append(LINE_SEP);
if (sLogBorderSwitch) {
if (CONFIG.mLogBorderSwitch) {
sb.append(TOP_BORDER).append(LINE_SEP);
for (String aHead : head) {
sb.append(LEFT_BORDER).append(aHead).append(LINE_SEP);
......@@ -376,7 +360,7 @@ public final class LogUtils {
}
private static void printBorder(final int type, final String tag, boolean isTop) {
if (sLogBorderSwitch) {
if (CONFIG.mLogBorderSwitch) {
Log.println(type, tag, isTop ? TOP_BORDER : BOTTOM_BORDER);
}
}
......@@ -384,9 +368,9 @@ public final class LogUtils {
private static void printHead(final int type, final String tag, final String[] head) {
if (head != null) {
for (String aHead : head) {
Log.println(type, tag, sLogBorderSwitch ? LEFT_BORDER + aHead : aHead);
Log.println(type, tag, CONFIG.mLogBorderSwitch ? LEFT_BORDER + aHead : aHead);
}
if (sLogBorderSwitch) Log.println(type, tag, MIDDLE_BORDER);
if (CONFIG.mLogBorderSwitch) Log.println(type, tag, MIDDLE_BORDER);
}
}
......@@ -411,7 +395,7 @@ public final class LogUtils {
int len = msg.length();
int countOfSub = len / MAX_LEN;
if (countOfSub > 0) {
if (sLogBorderSwitch) {
if (CONFIG.mLogBorderSwitch) {
Log.println(type, tag, msg.substring(0, MAX_LEN) + LINE_SEP + BOTTOM_BORDER);
int index = MAX_LEN;
for (int i = 1; i < countOfSub; i++) {
......@@ -440,7 +424,7 @@ public final class LogUtils {
}
private static void printSubMsg(final int type, final String tag, final String msg) {
if (!sLogBorderSwitch) {
if (!CONFIG.mLogBorderSwitch) {
Log.println(type, tag, msg);
return;
}
......@@ -452,7 +436,7 @@ public final class LogUtils {
}
private static void printSubMsg1(final int type, final String tag, final String msg) {
if (!sLogBorderSwitch) {
if (!CONFIG.mLogBorderSwitch) {
return;
}
......@@ -469,9 +453,10 @@ public final class LogUtils {
String date = format.substring(0, 5);
String time = format.substring(6);
final String fullPath =
(sDir == null ? sDefaultDir : sDir) + sFilePrefix + "-" + date + ".txt";
(CONFIG.mDir == null ? CONFIG.mDefaultDir : CONFIG.mDir)
+ CONFIG.mFilePrefix + "-" + date + ".txt";
if (!createOrExistsFile(fullPath)) {
Log.e(tag, "log to " + fullPath + " failed!");
Log.e("LogUtils", "create " + fullPath + " failed!");
return;
}
StringBuilder sb = new StringBuilder();
......@@ -482,11 +467,7 @@ public final class LogUtils {
.append(msg)
.append(LINE_SEP);
final String content = sb.toString();
if (input2File(content, fullPath)) {
Log.d(tag, "log to " + fullPath + " success!");
} else {
Log.e(tag, "log to " + fullPath + " failed!");
}
input2File(content, fullPath);
}
private static boolean createOrExistsFile(final String filePath) {
......@@ -542,7 +523,7 @@ public final class LogUtils {
return true;
}
private static boolean input2File(final String input, final String filePath) {
private static void input2File(final String input, final String filePath) {
if (sExecutor == null) {
sExecutor = Executors.newSingleThreadExecutor();
}
......@@ -569,119 +550,134 @@ public final class LogUtils {
}
});
try {
return submit.get();
if (submit.get()) return;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return false;
Log.e("LogUtils", "log to " + filePath + " failed!");
}
public static class Config {
private String mDefaultDir;// The default storage directory of log.
private String mDir; // The storage directory of log.
private String mFilePrefix = "util";// The file prefix of log.
private boolean mLogSwitch = true; // The switch of log.
private boolean mLog2ConsoleSwitch = true; // The logcat's switch of log.
private String mGlobalTag = null; // The global tag of log.
private boolean mTagIsSpace = true; // The global tag is space.
private boolean mLogHeadSwitch = true; // The head's switch of log.
private boolean mLog2FileSwitch = false; // The file's switch of log.
private boolean mLogBorderSwitch = true; // The border's switch of log.
private boolean mSingleTagSwitch = true; // The single tag of log.
private int mConsoleFilter = V; // The console's filter of log.
private int mFileFilter = V; // The file's filter of log.
private int mStackDeep = 1; // The stack's deep of log.
private Config() {
if (sDefaultDir != null) return;
if (mDefaultDir != null) return;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
&& Utils.getApp().getExternalCacheDir() != null)
sDefaultDir = Utils.getApp().getExternalCacheDir() + FILE_SEP + "log" + FILE_SEP;
mDefaultDir = Utils.getApp().getExternalCacheDir() + FILE_SEP + "log" + FILE_SEP;
else {
sDefaultDir = Utils.getApp().getCacheDir() + FILE_SEP + "log" + FILE_SEP;
mDefaultDir = Utils.getApp().getCacheDir() + FILE_SEP + "log" + FILE_SEP;
}
}
public Config setLogSwitch(final boolean logSwitch) {
sLogSwitch = logSwitch;
mLogSwitch = logSwitch;
return this;
}
public Config setConsoleSwitch(final boolean consoleSwitch) {
sLog2ConsoleSwitch = consoleSwitch;
mLog2ConsoleSwitch = consoleSwitch;
return this;
}
public Config setGlobalTag(final String tag) {
if (isSpace(tag)) {
sGlobalTag = "";
sTagIsSpace = true;
mGlobalTag = "";
mTagIsSpace = true;
} else {
sGlobalTag = tag;
sTagIsSpace = false;
mGlobalTag = tag;
mTagIsSpace = false;
}
return this;
}
public Config setLogHeadSwitch(final boolean logHeadSwitch) {
sLogHeadSwitch = logHeadSwitch;
mLogHeadSwitch = logHeadSwitch;
return this;
}
public Config setLog2FileSwitch(final boolean log2FileSwitch) {
sLog2FileSwitch = log2FileSwitch;
mLog2FileSwitch = log2FileSwitch;
return this;
}
public Config setDir(final String dir) {
if (isSpace(dir)) {
sDir = null;
mDir = null;
} else {
sDir = dir.endsWith(FILE_SEP) ? dir : dir + FILE_SEP;
mDir = dir.endsWith(FILE_SEP) ? dir : dir + FILE_SEP;
}
return this;
}
public Config setDir(final File dir) {
sDir = dir == null ? null : dir.getAbsolutePath() + FILE_SEP;
mDir = dir == null ? null : dir.getAbsolutePath() + FILE_SEP;
return this;
}
public Config setFilePrefix(final String filePrefix) {
if (isSpace(filePrefix)) {
sFilePrefix = "util";
mFilePrefix = "util";
} else {
sFilePrefix = filePrefix;
mFilePrefix = filePrefix;
}
return this;
}
public Config setBorderSwitch(final boolean borderSwitch) {
sLogBorderSwitch = borderSwitch;
mLogBorderSwitch = borderSwitch;
return this;
}
public Config setSingleTagSwitch(final boolean singleTagSwitch) {
sSingleTagSwitch = singleTagSwitch;
mSingleTagSwitch = singleTagSwitch;
return this;
}
public Config setConsoleFilter(@TYPE final int consoleFilter) {
sConsoleFilter = consoleFilter;
mConsoleFilter = consoleFilter;
return this;
}
public Config setFileFilter(@TYPE final int fileFilter) {
sFileFilter = fileFilter;
mFileFilter = fileFilter;
return this;
}
public Config setStackDeep(@IntRange(from = 1) final int stackDeep) {
sStackDeep = stackDeep;
mStackDeep = stackDeep;
return this;
}
@Override
public String toString() {
return "switch: " + sLogSwitch
+ LINE_SEP + "console: " + sLog2ConsoleSwitch
+ LINE_SEP + "tag: " + (sTagIsSpace ? "null" : sGlobalTag)
+ LINE_SEP + "head: " + sLogHeadSwitch
+ LINE_SEP + "file: " + sLog2FileSwitch
+ LINE_SEP + "dir: " + (sDir == null ? sDefaultDir : sDir)
+ LINE_SEP + "filePrefix: " + sFilePrefix
+ LINE_SEP + "border: " + sLogBorderSwitch
+ LINE_SEP + "singleTag: " + sSingleTagSwitch
+ LINE_SEP + "consoleFilter: " + T[sConsoleFilter - V]
+ LINE_SEP + "fileFilter: " + T[sFileFilter - V]
+ LINE_SEP + "stackDeep: " + sStackDeep;
return "switch: " + mLogSwitch
+ LINE_SEP + "console: " + mLog2ConsoleSwitch
+ LINE_SEP + "tag: " + (mTagIsSpace ? "null" : mGlobalTag)
+ LINE_SEP + "head: " + mLogHeadSwitch
+ LINE_SEP + "file: " + mLog2FileSwitch
+ LINE_SEP + "dir: " + (mDir == null ? mDefaultDir : mDir)
+ LINE_SEP + "filePrefix: " + mFilePrefix
+ LINE_SEP + "border: " + mLogBorderSwitch
+ LINE_SEP + "singleTag: " + mSingleTagSwitch
+ LINE_SEP + "consoleFilter: " + T[mConsoleFilter - V]
+ LINE_SEP + "fileFilter: " + T[mFileFilter - V]
+ LINE_SEP + "stackDeep: " + mStackDeep;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册