| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231 |
- package com.cooleshow.base.utils;
- import android.content.ClipData;
- import android.content.ComponentName;
- import android.content.Intent;
- import android.graphics.Rect;
- import android.net.Uri;
- import android.os.Build;
- import android.os.Bundle;
- import android.util.Log;
- import org.json.JSONArray;
- import org.json.JSONException;
- import org.json.JSONObject;
- import java.io.File;
- import java.io.FilenameFilter;
- import java.io.IOException;
- import java.io.StringReader;
- import java.io.StringWriter;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.reflect.ParameterizedType;
- import java.lang.reflect.Type;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Collections;
- import java.util.Date;
- import java.util.Formatter;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Locale;
- import java.util.Map;
- import java.util.Set;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- import javax.xml.transform.OutputKeys;
- import javax.xml.transform.Source;
- import javax.xml.transform.Transformer;
- import javax.xml.transform.TransformerFactory;
- import javax.xml.transform.stream.StreamResult;
- import javax.xml.transform.stream.StreamSource;
- import androidx.annotation.IntDef;
- import androidx.annotation.IntRange;
- import androidx.annotation.RequiresApi;
- import androidx.collection.SimpleArrayMap;
- /**
- * <pre>
- * author: Blankj
- * blog : http://blankj.com
- * time : 2016/09/21
- * desc : utils about log
- * </pre>
- */
- public final class LogUtils {
- public static final int V = Log.VERBOSE;
- public static final int D = Log.DEBUG;
- public static final int I = Log.INFO;
- public static final int W = Log.WARN;
- public static final int E = Log.ERROR;
- public static final int A = Log.ASSERT;
- @IntDef({V, D, I, W, E, A})
- @Retention(RetentionPolicy.SOURCE)
- public @interface TYPE {
- }
- private static final char[] T = new char[]{'V', 'D', 'I', 'W', 'E', 'A'};
- private static final int FILE = 0x10;
- private static final int JSON = 0x20;
- private static final int XML = 0x30;
- private static final String FILE_SEP = System.getProperty("file.separator");
- private static final String LINE_SEP = System.getProperty("line.separator");
- private static final String TOP_CORNER = "┌";
- private static final String MIDDLE_CORNER = "├";
- private static final String LEFT_BORDER = "│ ";
- private static final String BOTTOM_CORNER = "└";
- private static final String SIDE_DIVIDER =
- "────────────────────────────────────────────────────────";
- private static final String MIDDLE_DIVIDER =
- "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄";
- private static final String TOP_BORDER = TOP_CORNER + SIDE_DIVIDER + SIDE_DIVIDER;
- private static final String MIDDLE_BORDER = MIDDLE_CORNER + MIDDLE_DIVIDER + MIDDLE_DIVIDER;
- private static final String BOTTOM_BORDER = BOTTOM_CORNER + SIDE_DIVIDER + SIDE_DIVIDER;
- private static final int MAX_LEN = 1100;// fit for Chinese character
- private static final String NOTHING = "log nothing";
- private static final String NULL = "null";
- private static final String ARGS = "args";
- private static final String PLACEHOLDER = " ";
- private static final Config CONFIG = new Config();
- private static SimpleDateFormat simpleDateFormat;
- private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
- private static final SimpleArrayMap<Class, IFormatter> I_FORMATTER_MAP = new SimpleArrayMap<>();
- private LogUtils() {
- throw new UnsupportedOperationException("u can't instantiate me...");
- }
- public static Config getConfig() {
- return CONFIG;
- }
- public static void v(final Object... contents) {
- log(V, CONFIG.getGlobalTag(), contents);
- }
- public static void vTag(final String tag, final Object... contents) {
- log(V, tag, contents);
- }
- public static void d(final Object... contents) {
- log(D, CONFIG.getGlobalTag(), contents);
- }
- public static void dTag(final String tag, final Object... contents) {
- log(D, tag, contents);
- }
- public static void i(final Object... contents) {
- log(I, CONFIG.getGlobalTag(), contents);
- }
- public static void iTag(final String tag, final Object... contents) {
- log(I, tag, contents);
- }
- public static void w(final Object... contents) {
- log(W, CONFIG.getGlobalTag(), contents);
- }
- public static void wTag(final String tag, final Object... contents) {
- log(W, tag, contents);
- }
- public static void e(final Object... contents) {
- log(E, CONFIG.getGlobalTag(), contents);
- }
- public static void eTag(final String tag, final Object... contents) {
- log(E, tag, contents);
- }
- public static void a(final Object... contents) {
- log(A, CONFIG.getGlobalTag(), contents);
- }
- public static void aTag(final String tag, final Object... contents) {
- log(A, tag, contents);
- }
- public static void file(final Object content) {
- log(FILE | D, CONFIG.getGlobalTag(), content);
- }
- public static void file(@TYPE final int type, final Object content) {
- log(FILE | type, CONFIG.getGlobalTag(), content);
- }
- public static void file(final String tag, final Object content) {
- log(FILE | D, tag, content);
- }
- public static void file(@TYPE final int type, final String tag, final Object content) {
- log(FILE | type, tag, content);
- }
- public static void json(final Object content) {
- log(JSON | D, CONFIG.getGlobalTag(), content);
- }
- public static void json(@TYPE final int type, final Object content) {
- log(JSON | type, CONFIG.getGlobalTag(), content);
- }
- public static void json(final String tag, final Object content) {
- log(JSON | D, tag, content);
- }
- public static void json(@TYPE final int type, final String tag, final Object content) {
- log(JSON | type, tag, content);
- }
- public static void xml(final String content) {
- log(XML | D, CONFIG.getGlobalTag(), content);
- }
- public static void xml(@TYPE final int type, final String content) {
- log(XML | type, CONFIG.getGlobalTag(), content);
- }
- public static void xml(final String tag, final String content) {
- log(XML | D, tag, content);
- }
- public static void xml(@TYPE final int type, final String tag, final String content) {
- log(XML | type, tag, content);
- }
- public static void log(final int type, final String tag, final Object... contents) {
- if (!CONFIG.isLogSwitch()) return;
- final int type_low = type & 0x0f, type_high = type & 0xf0;
- if (CONFIG.isLog2ConsoleSwitch() || CONFIG.isLog2FileSwitch() || type_high == FILE) {
- if (type_low < CONFIG.mConsoleFilter && type_low < CONFIG.mFileFilter) return;
- final TagHead tagHead = processTagAndHead(tag);
- final String body = processBody(type_high, contents);
- if (CONFIG.isLog2ConsoleSwitch() && type_high != FILE && type_low >= CONFIG.mConsoleFilter) {
- print2Console(type_low, tagHead.tag, tagHead.consoleHead, body);
- }
- if ((CONFIG.isLog2FileSwitch() || type_high == FILE) && type_low >= CONFIG.mFileFilter) {
- EXECUTOR.execute(new Runnable() {
- @Override
- public void run() {
- print2File(type_low, tagHead.tag, tagHead.fileHead + body);
- }
- });
- }
- }
- }
- public static String getCurrentLogFilePath() {
- return getCurrentLogFilePath(new Date());
- }
- public static List<File> getLogFiles() {
- String dir = CONFIG.getDir();
- File logDir = new File(dir);
- if (!logDir.exists()) return new ArrayList<>();
- File[] files = logDir.listFiles(new FilenameFilter() {
- @Override
- public boolean accept(File dir, String name) {
- return isMatchLogFileName(name);
- }
- });
- List<File> list = new ArrayList<>();
- Collections.addAll(list, files);
- return list;
- }
- private static TagHead processTagAndHead(String tag) {
- if (!CONFIG.mTagIsSpace && !CONFIG.isLogHeadSwitch()) {
- tag = CONFIG.getGlobalTag();
- } else {
- final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
- final int stackIndex = 3 + CONFIG.getStackOffset();
- if (stackIndex >= stackTrace.length) {
- StackTraceElement targetElement = stackTrace[3];
- final String fileName = getFileName(targetElement);
- if (CONFIG.mTagIsSpace && UtilsBridge.isSpace(tag)) {
- int index = fileName.indexOf('.');// Use proguard may not find '.'.
- tag = index == -1 ? fileName : fileName.substring(0, index);
- }
- return new TagHead(tag, null, ": ");
- }
- StackTraceElement targetElement = stackTrace[stackIndex];
- final String fileName = getFileName(targetElement);
- if (CONFIG.mTagIsSpace && UtilsBridge.isSpace(tag)) {
- int index = fileName.indexOf('.');// Use proguard may not find '.'.
- tag = index == -1 ? fileName : fileName.substring(0, index);
- }
- if (CONFIG.isLogHeadSwitch()) {
- String tName = Thread.currentThread().getName();
- final String head = new Formatter()
- .format("%s, %s.%s(%s:%d)",
- tName,
- targetElement.getClassName(),
- targetElement.getMethodName(),
- fileName,
- targetElement.getLineNumber())
- .toString();
- final String fileHead = " [" + head + "]: ";
- if (CONFIG.getStackDeep() <= 1) {
- return new TagHead(tag, new String[]{head}, fileHead);
- } else {
- final String[] consoleHead =
- new String[Math.min(
- CONFIG.getStackDeep(),
- stackTrace.length - stackIndex
- )];
- consoleHead[0] = head;
- int spaceLen = tName.length() + 2;
- String space = new Formatter().format("%" + spaceLen + "s", "").toString();
- for (int i = 1, len = consoleHead.length; i < len; ++i) {
- targetElement = stackTrace[i + stackIndex];
- consoleHead[i] = new Formatter()
- .format("%s%s.%s(%s:%d)",
- space,
- targetElement.getClassName(),
- targetElement.getMethodName(),
- getFileName(targetElement),
- targetElement.getLineNumber())
- .toString();
- }
- return new TagHead(tag, consoleHead, fileHead);
- }
- }
- }
- return new TagHead(tag, null, ": ");
- }
- private static String getFileName(final StackTraceElement targetElement) {
- String fileName = targetElement.getFileName();
- if (fileName != null) return fileName;
- // If name of file is null, should add
- // "-keepattributes SourceFile,LineNumberTable" in proguard file.
- String className = targetElement.getClassName();
- String[] classNameInfo = className.split("\\.");
- if (classNameInfo.length > 0) {
- className = classNameInfo[classNameInfo.length - 1];
- }
- int index = className.indexOf('$');
- if (index != -1) {
- className = className.substring(0, index);
- }
- return className + ".java";
- }
- private static String processBody(final int type, final Object... contents) {
- String body = NULL;
- if (contents != null) {
- if (contents.length == 1) {
- body = formatObject(type, contents[0]);
- } else {
- StringBuilder sb = new StringBuilder();
- for (int i = 0, len = contents.length; i < len; ++i) {
- Object content = contents[i];
- sb.append(ARGS)
- .append("[")
- .append(i)
- .append("]")
- .append(" = ")
- .append(formatObject(content))
- .append(LINE_SEP);
- }
- body = sb.toString();
- }
- }
- return body.length() == 0 ? NOTHING : body;
- }
- private static String formatObject(int type, Object object) {
- if (object == null) return NULL;
- if (type == JSON) return LogFormatter.object2String(object, JSON);
- if (type == XML) return LogFormatter.object2String(object, XML);
- return formatObject(object);
- }
- private static String formatObject(Object object) {
- if (object == null) return NULL;
- if (!I_FORMATTER_MAP.isEmpty()) {
- IFormatter iFormatter = I_FORMATTER_MAP.get(getClassFromObject(object));
- if (iFormatter != null) {
- //noinspection unchecked
- return iFormatter.format(object);
- }
- }
- return LogFormatter.object2String(object);
- }
- private static void print2Console(final int type,
- final String tag,
- final String[] head,
- final String msg) {
- if (CONFIG.isSingleTagSwitch()) {
- printSingleTagMsg(type, tag, processSingleTagMsg(type, tag, head, msg));
- } else {
- printBorder(type, tag, true);
- printHead(type, tag, head);
- printMsg(type, tag, msg);
- printBorder(type, tag, false);
- }
- }
- private static void printBorder(final int type, final String tag, boolean isTop) {
- if (CONFIG.isLogBorderSwitch()) {
- print2Console(type, tag, isTop ? TOP_BORDER : BOTTOM_BORDER);
- }
- }
- private static void printHead(final int type, final String tag, final String[] head) {
- if (head != null) {
- for (String aHead : head) {
- print2Console(type, tag, CONFIG.isLogBorderSwitch() ? LEFT_BORDER + aHead : aHead);
- }
- if (CONFIG.isLogBorderSwitch()) print2Console(type, tag, MIDDLE_BORDER);
- }
- }
- private static void printMsg(final int type, final String tag, final String msg) {
- int len = msg.length();
- int countOfSub = len / MAX_LEN;
- if (countOfSub > 0) {
- int index = 0;
- for (int i = 0; i < countOfSub; i++) {
- printSubMsg(type, tag, msg.substring(index, index + MAX_LEN));
- index += MAX_LEN;
- }
- if (index != len) {
- printSubMsg(type, tag, msg.substring(index, len));
- }
- } else {
- printSubMsg(type, tag, msg);
- }
- }
- private static void printSubMsg(final int type, final String tag, final String msg) {
- if (!CONFIG.isLogBorderSwitch()) {
- print2Console(type, tag, msg);
- return;
- }
- StringBuilder sb = new StringBuilder();
- String[] lines = msg.split(LINE_SEP);
- for (String line : lines) {
- print2Console(type, tag, LEFT_BORDER + line);
- }
- }
- private static String processSingleTagMsg(final int type,
- final String tag,
- final String[] head,
- final String msg) {
- StringBuilder sb = new StringBuilder();
- if (CONFIG.isLogBorderSwitch()) {
- sb.append(PLACEHOLDER).append(LINE_SEP);
- sb.append(TOP_BORDER).append(LINE_SEP);
- if (head != null) {
- for (String aHead : head) {
- sb.append(LEFT_BORDER).append(aHead).append(LINE_SEP);
- }
- sb.append(MIDDLE_BORDER).append(LINE_SEP);
- }
- for (String line : msg.split(LINE_SEP)) {
- sb.append(LEFT_BORDER).append(line).append(LINE_SEP);
- }
- sb.append(BOTTOM_BORDER);
- } else {
- if (head != null) {
- sb.append(PLACEHOLDER).append(LINE_SEP);
- for (String aHead : head) {
- sb.append(aHead).append(LINE_SEP);
- }
- }
- sb.append(msg);
- }
- return sb.toString();
- }
- private static void printSingleTagMsg(final int type, final String tag, final String msg) {
- int len = msg.length();
- int countOfSub = CONFIG.isLogBorderSwitch() ? (len - BOTTOM_BORDER.length()) / MAX_LEN : len / MAX_LEN;
- if (countOfSub > 0) {
- if (CONFIG.isLogBorderSwitch()) {
- print2Console(type, tag, msg.substring(0, MAX_LEN) + LINE_SEP + BOTTOM_BORDER);
- int index = MAX_LEN;
- for (int i = 1; i < countOfSub; i++) {
- print2Console(type, tag, PLACEHOLDER + LINE_SEP + TOP_BORDER + LINE_SEP
- + LEFT_BORDER + msg.substring(index, index + MAX_LEN)
- + LINE_SEP + BOTTOM_BORDER);
- index += MAX_LEN;
- }
- if (index != len - BOTTOM_BORDER.length()) {
- print2Console(type, tag, PLACEHOLDER + LINE_SEP + TOP_BORDER + LINE_SEP
- + LEFT_BORDER + msg.substring(index, len));
- }
- } else {
- print2Console(type, tag, msg.substring(0, MAX_LEN));
- int index = MAX_LEN;
- for (int i = 1; i < countOfSub; i++) {
- print2Console(type, tag,
- PLACEHOLDER + LINE_SEP + msg.substring(index, index + MAX_LEN));
- index += MAX_LEN;
- }
- if (index != len) {
- print2Console(type, tag, PLACEHOLDER + LINE_SEP + msg.substring(index, len));
- }
- }
- } else {
- print2Console(type, tag, msg);
- }
- }
- private static void print2Console(int type, String tag, String msg) {
- Log.println(type, tag, msg);
- if (CONFIG.mOnConsoleOutputListener != null) {
- CONFIG.mOnConsoleOutputListener.onConsoleOutput(type, tag, msg);
- }
- }
- private static void print2File(final int type, final String tag, final String msg) {
- Date d = new Date();
- String format = getSdf().format(d);
- String date = format.substring(0, 10);
- String currentLogFilePath = getCurrentLogFilePath(d);
- if (!createOrExistsFile(currentLogFilePath, date)) {
- Log.e("LogUtils", "create " + currentLogFilePath + " failed!");
- return;
- }
- String time = format.substring(11);
- final String content = time +
- T[type - V] +
- "/" +
- tag +
- msg +
- LINE_SEP;
- input2File(currentLogFilePath, content);
- }
- private static String getCurrentLogFilePath(Date d) {
- String format = getSdf().format(d);
- String date = format.substring(0, 10);
- return CONFIG.getDir() + CONFIG.getFilePrefix() + "_"
- + date + "_" +
- CONFIG.getProcessName() + CONFIG.getFileExtension();
- }
- private static SimpleDateFormat getSdf() {
- if (simpleDateFormat == null) {
- simpleDateFormat = new SimpleDateFormat("yyyy_MM_dd HH:mm:ss.SSS ", Locale.getDefault());
- }
- return simpleDateFormat;
- }
- private static boolean createOrExistsFile(final String filePath, final String date) {
- File file = new File(filePath);
- if (file.exists()) return file.isFile();
- if (!UtilsBridge.createOrExistsDir(file.getParentFile())) return false;
- try {
- deleteDueLogs(filePath, date);
- boolean isCreate = file.createNewFile();
- if (isCreate) {
- printDeviceInfo(filePath, date);
- }
- return isCreate;
- } catch (IOException e) {
- e.printStackTrace();
- return false;
- }
- }
- private static void deleteDueLogs(final String filePath, final String date) {
- if (CONFIG.getSaveDays() <= 0) return;
- File file = new File(filePath);
- File parentFile = file.getParentFile();
- File[] files = parentFile.listFiles(new FilenameFilter() {
- @Override
- public boolean accept(File dir, String name) {
- return isMatchLogFileName(name);
- }
- });
- if (files == null || files.length <= 0) return;
- final SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd", Locale.getDefault());
- try {
- long dueMillis = sdf.parse(date).getTime() - CONFIG.getSaveDays() * 86400000L;
- for (final File aFile : files) {
- String name = aFile.getName();
- int l = name.length();
- String logDay = findDate(name);
- if (sdf.parse(logDay).getTime() <= dueMillis) {
- EXECUTOR.execute(new Runnable() {
- @Override
- public void run() {
- boolean delete = aFile.delete();
- if (!delete) {
- Log.e("LogUtils", "delete " + aFile + " failed!");
- }
- }
- });
- }
- }
- } catch (ParseException e) {
- e.printStackTrace();
- }
- }
- private static boolean isMatchLogFileName(String name) {
- return name.matches("^" + CONFIG.getFilePrefix() + "_[0-9]{4}_[0-9]{2}_[0-9]{2}_.*$");
- }
- private static String findDate(String str) {
- Pattern pattern = Pattern.compile("[0-9]{4}_[0-9]{2}_[0-9]{2}");
- Matcher matcher = pattern.matcher(str);
- if (matcher.find()) {
- return matcher.group();
- }
- return "";
- }
- private static void printDeviceInfo(final String filePath, final String date) {
- CONFIG.mFileHead.addFirst("Date of Log", date);
- input2File(filePath, CONFIG.mFileHead.toString());
- }
- private static void input2File(final String filePath, final String input) {
- if (CONFIG.mFileWriter == null) {
- UtilsBridge.writeFileFromString(filePath, input, true);
- } else {
- CONFIG.mFileWriter.write(filePath, input);
- }
- if (CONFIG.mOnFileOutputListener != null) {
- CONFIG.mOnFileOutputListener.onFileOutput(filePath, input);
- }
- }
- public static final 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 String mFileExtension = ".txt";// The file extension of log.
- private boolean mLogSwitch = true; // The switch of log.
- private boolean mLog2ConsoleSwitch = true; // The logcat's switch of log.
- private String mGlobalTag = ""; // 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 int mStackOffset = 0; // The stack's offset of log.
- private int mSaveDays = -1; // The save days of log.
- private String mProcessName = UtilsBridge.getCurrentProcessName();
- private IFileWriter mFileWriter;
- private OnConsoleOutputListener mOnConsoleOutputListener;
- private OnFileOutputListener mOnFileOutputListener;
- private UtilsBridge.FileHead mFileHead = new UtilsBridge.FileHead("Log");
- private Config() {
- if (UtilsBridge.isSDCardEnableByEnvironment()
- && Utils.getApp().getExternalFilesDir(null) != null)
- mDefaultDir = Utils.getApp().getExternalFilesDir(null) + FILE_SEP + "log" + FILE_SEP;
- else {
- mDefaultDir = Utils.getApp().getFilesDir() + FILE_SEP + "log" + FILE_SEP;
- }
- }
- public final Config setLogSwitch(final boolean logSwitch) {
- mLogSwitch = logSwitch;
- return this;
- }
- public final Config setConsoleSwitch(final boolean consoleSwitch) {
- mLog2ConsoleSwitch = consoleSwitch;
- return this;
- }
- public final Config setGlobalTag(final String tag) {
- if (UtilsBridge.isSpace(tag)) {
- mGlobalTag = "";
- mTagIsSpace = true;
- } else {
- mGlobalTag = tag;
- mTagIsSpace = false;
- }
- return this;
- }
- public final Config setLogHeadSwitch(final boolean logHeadSwitch) {
- mLogHeadSwitch = logHeadSwitch;
- return this;
- }
- public final Config setLog2FileSwitch(final boolean log2FileSwitch) {
- mLog2FileSwitch = log2FileSwitch;
- return this;
- }
- public final Config setDir(final String dir) {
- if (UtilsBridge.isSpace(dir)) {
- mDir = null;
- } else {
- mDir = dir.endsWith(FILE_SEP) ? dir : dir + FILE_SEP;
- }
- return this;
- }
- public final Config setDir(final File dir) {
- mDir = dir == null ? null : (dir.getAbsolutePath() + FILE_SEP);
- return this;
- }
- public final Config setFilePrefix(final String filePrefix) {
- if (UtilsBridge.isSpace(filePrefix)) {
- mFilePrefix = "util";
- } else {
- mFilePrefix = filePrefix;
- }
- return this;
- }
- public final Config setFileExtension(final String fileExtension) {
- if (UtilsBridge.isSpace(fileExtension)) {
- mFileExtension = ".txt";
- } else {
- if (fileExtension.startsWith(".")) {
- mFileExtension = fileExtension;
- } else {
- mFileExtension = "." + fileExtension;
- }
- }
- return this;
- }
- public final Config setBorderSwitch(final boolean borderSwitch) {
- mLogBorderSwitch = borderSwitch;
- return this;
- }
- public final Config setSingleTagSwitch(final boolean singleTagSwitch) {
- mSingleTagSwitch = singleTagSwitch;
- return this;
- }
- public final Config setConsoleFilter(@TYPE final int consoleFilter) {
- mConsoleFilter = consoleFilter;
- return this;
- }
- public final Config setFileFilter(@TYPE final int fileFilter) {
- mFileFilter = fileFilter;
- return this;
- }
- public final Config setStackDeep(@IntRange(from = 1) final int stackDeep) {
- mStackDeep = stackDeep;
- return this;
- }
- public final Config setStackOffset(@IntRange(from = 0) final int stackOffset) {
- mStackOffset = stackOffset;
- return this;
- }
- public final Config setSaveDays(@IntRange(from = 1) final int saveDays) {
- mSaveDays = saveDays;
- return this;
- }
- public final <T> Config addFormatter(final IFormatter<T> iFormatter) {
- if (iFormatter != null) {
- I_FORMATTER_MAP.put(getTypeClassFromParadigm(iFormatter), iFormatter);
- }
- return this;
- }
- public final Config setFileWriter(final IFileWriter fileWriter) {
- mFileWriter = fileWriter;
- return this;
- }
- public final Config setOnConsoleOutputListener(final OnConsoleOutputListener listener) {
- mOnConsoleOutputListener = listener;
- return this;
- }
- public final Config setOnFileOutputListener(final OnFileOutputListener listener) {
- mOnFileOutputListener = listener;
- return this;
- }
- public final Config addFileExtraHead(final Map<String, String> fileExtraHead) {
- mFileHead.append(fileExtraHead);
- return this;
- }
- public final Config addFileExtraHead(final String key, final String value) {
- mFileHead.append(key, value);
- return this;
- }
- public final String getProcessName() {
- if (mProcessName == null) return "";
- return mProcessName.replace(":", "_");
- }
- public final String getDefaultDir() {
- return mDefaultDir;
- }
- public final String getDir() {
- return mDir == null ? mDefaultDir : mDir;
- }
- public final String getFilePrefix() {
- return mFilePrefix;
- }
- public final String getFileExtension() {
- return mFileExtension;
- }
- public final boolean isLogSwitch() {
- return mLogSwitch;
- }
- public final boolean isLog2ConsoleSwitch() {
- return mLog2ConsoleSwitch;
- }
- public final String getGlobalTag() {
- if (UtilsBridge.isSpace(mGlobalTag)) return "";
- return mGlobalTag;
- }
- public final boolean isLogHeadSwitch() {
- return mLogHeadSwitch;
- }
- public final boolean isLog2FileSwitch() {
- return mLog2FileSwitch;
- }
- public final boolean isLogBorderSwitch() {
- return mLogBorderSwitch;
- }
- public final boolean isSingleTagSwitch() {
- return mSingleTagSwitch;
- }
- public final char getConsoleFilter() {
- return T[mConsoleFilter - V];
- }
- public final char getFileFilter() {
- return T[mFileFilter - V];
- }
- public final int getStackDeep() {
- return mStackDeep;
- }
- public final int getStackOffset() {
- return mStackOffset;
- }
- public final int getSaveDays() {
- return mSaveDays;
- }
- public final boolean haveSetOnConsoleOutputListener() {
- return mOnConsoleOutputListener != null;
- }
- public final boolean haveSetOnFileOutputListener() {
- return mOnFileOutputListener != null;
- }
- @Override
- public String toString() {
- return "process: " + getProcessName()
- + LINE_SEP + "logSwitch: " + isLogSwitch()
- + LINE_SEP + "consoleSwitch: " + isLog2ConsoleSwitch()
- + LINE_SEP + "tag: " + (getGlobalTag().equals("") ? "null" : getGlobalTag())
- + LINE_SEP + "headSwitch: " + isLogHeadSwitch()
- + LINE_SEP + "fileSwitch: " + isLog2FileSwitch()
- + LINE_SEP + "dir: " + getDir()
- + LINE_SEP + "filePrefix: " + getFilePrefix()
- + LINE_SEP + "borderSwitch: " + isLogBorderSwitch()
- + LINE_SEP + "singleTagSwitch: " + isSingleTagSwitch()
- + LINE_SEP + "consoleFilter: " + getConsoleFilter()
- + LINE_SEP + "fileFilter: " + getFileFilter()
- + LINE_SEP + "stackDeep: " + getStackDeep()
- + LINE_SEP + "stackOffset: " + getStackOffset()
- + LINE_SEP + "saveDays: " + getSaveDays()
- + LINE_SEP + "formatter: " + I_FORMATTER_MAP
- + LINE_SEP + "fileWriter: " + mFileWriter
- + LINE_SEP + "onConsoleOutputListener: " + mOnConsoleOutputListener
- + LINE_SEP + "onFileOutputListener: " + mOnFileOutputListener
- + LINE_SEP + "fileExtraHeader: " + mFileHead.getAppended();
- }
- }
- public abstract static class IFormatter<T> {
- public abstract String format(T t);
- }
- public interface IFileWriter {
- void write(String file, String content);
- }
- public interface OnConsoleOutputListener {
- void onConsoleOutput(@TYPE int type, String tag, String content);
- }
- public interface OnFileOutputListener {
- void onFileOutput(String filePath, String content);
- }
- private final static class TagHead {
- String tag;
- String[] consoleHead;
- String fileHead;
- TagHead(String tag, String[] consoleHead, String fileHead) {
- this.tag = tag;
- this.consoleHead = consoleHead;
- this.fileHead = fileHead;
- }
- }
- private final static class LogFormatter {
- static String object2String(Object object) {
- return object2String(object, -1);
- }
- static String object2String(Object object, int type) {
- if (object.getClass().isArray()) return array2String(object);
- if (object instanceof Throwable)
- return UtilsBridge.getFullStackTrace((Throwable) object);
- if (object instanceof Bundle) return bundle2String((Bundle) object);
- if (object instanceof Intent) return intent2String((Intent) object);
- if (type == JSON) {
- return object2Json(object);
- } else if (type == XML) {
- return formatXml(object.toString());
- }
- return object.toString();
- }
- private static String bundle2String(Bundle bundle) {
- Iterator<String> iterator = bundle.keySet().iterator();
- if (!iterator.hasNext()) {
- return "Bundle {}";
- }
- StringBuilder sb = new StringBuilder(128);
- sb.append("Bundle { ");
- for (; ; ) {
- String key = iterator.next();
- Object value = bundle.get(key);
- sb.append(key).append('=');
- if (value instanceof Bundle) {
- sb.append(value == bundle ? "(this Bundle)" : bundle2String((Bundle) value));
- } else {
- sb.append(formatObject(value));
- }
- if (!iterator.hasNext()) return sb.append(" }").toString();
- sb.append(',').append(' ');
- }
- }
- private static String intent2String(Intent intent) {
- StringBuilder sb = new StringBuilder(128);
- sb.append("Intent { ");
- boolean first = true;
- String mAction = intent.getAction();
- if (mAction != null) {
- sb.append("act=").append(mAction);
- first = false;
- }
- Set<String> mCategories = intent.getCategories();
- if (mCategories != null) {
- if (!first) {
- sb.append(' ');
- }
- first = false;
- sb.append("cat=[");
- boolean firstCategory = true;
- for (String c : mCategories) {
- if (!firstCategory) {
- sb.append(',');
- }
- sb.append(c);
- firstCategory = false;
- }
- sb.append("]");
- }
- Uri mData = intent.getData();
- if (mData != null) {
- if (!first) {
- sb.append(' ');
- }
- first = false;
- sb.append("dat=").append(mData);
- }
- String mType = intent.getType();
- if (mType != null) {
- if (!first) {
- sb.append(' ');
- }
- first = false;
- sb.append("typ=").append(mType);
- }
- int mFlags = intent.getFlags();
- if (mFlags != 0) {
- if (!first) {
- sb.append(' ');
- }
- first = false;
- sb.append("flg=0x").append(Integer.toHexString(mFlags));
- }
- String mPackage = intent.getPackage();
- if (mPackage != null) {
- if (!first) {
- sb.append(' ');
- }
- first = false;
- sb.append("pkg=").append(mPackage);
- }
- ComponentName mComponent = intent.getComponent();
- if (mComponent != null) {
- if (!first) {
- sb.append(' ');
- }
- first = false;
- sb.append("cmp=").append(mComponent.flattenToShortString());
- }
- Rect mSourceBounds = intent.getSourceBounds();
- if (mSourceBounds != null) {
- if (!first) {
- sb.append(' ');
- }
- first = false;
- sb.append("bnds=").append(mSourceBounds.toShortString());
- }
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- ClipData mClipData = intent.getClipData();
- if (mClipData != null) {
- if (!first) {
- sb.append(' ');
- }
- first = false;
- clipData2String(mClipData, sb);
- }
- }
- Bundle mExtras = intent.getExtras();
- if (mExtras != null) {
- if (!first) {
- sb.append(' ');
- }
- first = false;
- sb.append("extras={");
- sb.append(bundle2String(mExtras));
- sb.append('}');
- }
- if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
- Intent mSelector = intent.getSelector();
- if (mSelector != null) {
- if (!first) {
- sb.append(' ');
- }
- first = false;
- sb.append("sel={");
- sb.append(mSelector == intent ? "(this Intent)" : intent2String(mSelector));
- sb.append("}");
- }
- }
- sb.append(" }");
- return sb.toString();
- }
- @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
- private static void clipData2String(ClipData clipData, StringBuilder sb) {
- ClipData.Item item = clipData.getItemAt(0);
- if (item == null) {
- sb.append("ClipData.Item {}");
- return;
- }
- sb.append("ClipData.Item { ");
- String mHtmlText = item.getHtmlText();
- if (mHtmlText != null) {
- sb.append("H:");
- sb.append(mHtmlText);
- sb.append("}");
- return;
- }
- CharSequence mText = item.getText();
- if (mText != null) {
- sb.append("T:");
- sb.append(mText);
- sb.append("}");
- return;
- }
- Uri uri = item.getUri();
- if (uri != null) {
- sb.append("U:").append(uri);
- sb.append("}");
- return;
- }
- Intent intent = item.getIntent();
- if (intent != null) {
- sb.append("I:");
- sb.append(intent2String(intent));
- sb.append("}");
- return;
- }
- sb.append("NULL");
- sb.append("}");
- }
- private static String object2Json(Object object) {
- if (object instanceof CharSequence) {
- return UtilsBridge.formatJson(object.toString());
- }
- try {
- return UtilsBridge.getGson4LogUtils().toJson(object);
- } catch (Throwable t) {
- return object.toString();
- }
- }
- private static String formatJson(String json) {
- try {
- for (int i = 0, len = json.length(); i < len; i++) {
- char c = json.charAt(i);
- if (c == '{') {
- return new JSONObject(json).toString(2);
- } else if (c == '[') {
- return new JSONArray(json).toString(2);
- } else if (!Character.isWhitespace(c)) {
- return json;
- }
- }
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return json;
- }
- private static String formatXml(String xml) {
- try {
- Source xmlInput = new StreamSource(new StringReader(xml));
- StreamResult xmlOutput = new StreamResult(new StringWriter());
- Transformer transformer = TransformerFactory.newInstance().newTransformer();
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
- transformer.transform(xmlInput, xmlOutput);
- xml = xmlOutput.getWriter().toString().replaceFirst(">", ">" + LINE_SEP);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return xml;
- }
- private static String array2String(Object object) {
- if (object instanceof Object[]) {
- return Arrays.deepToString((Object[]) object);
- } else if (object instanceof boolean[]) {
- return Arrays.toString((boolean[]) object);
- } else if (object instanceof byte[]) {
- return Arrays.toString((byte[]) object);
- } else if (object instanceof char[]) {
- return Arrays.toString((char[]) object);
- } else if (object instanceof double[]) {
- return Arrays.toString((double[]) object);
- } else if (object instanceof float[]) {
- return Arrays.toString((float[]) object);
- } else if (object instanceof int[]) {
- return Arrays.toString((int[]) object);
- } else if (object instanceof long[]) {
- return Arrays.toString((long[]) object);
- } else if (object instanceof short[]) {
- return Arrays.toString((short[]) object);
- }
- throw new IllegalArgumentException("Array has incompatible type: " + object.getClass());
- }
- }
- private static <T> Class getTypeClassFromParadigm(final IFormatter<T> formatter) {
- Type[] genericInterfaces = formatter.getClass().getGenericInterfaces();
- Type type;
- if (genericInterfaces.length == 1) {
- type = genericInterfaces[0];
- } else {
- type = formatter.getClass().getGenericSuperclass();
- }
- type = ((ParameterizedType) type).getActualTypeArguments()[0];
- while (type instanceof ParameterizedType) {
- type = ((ParameterizedType) type).getRawType();
- }
- String className = type.toString();
- if (className.startsWith("class ")) {
- className = className.substring(6);
- } else if (className.startsWith("interface ")) {
- className = className.substring(10);
- }
- try {
- return Class.forName(className);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- return null;
- }
- private static Class getClassFromObject(final Object obj) {
- Class objClass = obj.getClass();
- if (objClass.isAnonymousClass() || objClass.isSynthetic()) {
- Type[] genericInterfaces = objClass.getGenericInterfaces();
- String className;
- if (genericInterfaces.length == 1) {// interface
- Type type = genericInterfaces[0];
- while (type instanceof ParameterizedType) {
- type = ((ParameterizedType) type).getRawType();
- }
- className = type.toString();
- } else {// abstract class or lambda
- Type type = objClass.getGenericSuperclass();
- while (type instanceof ParameterizedType) {
- type = ((ParameterizedType) type).getRawType();
- }
- className = type.toString();
- }
- if (className.startsWith("class ")) {
- className = className.substring(6);
- } else if (className.startsWith("interface ")) {
- className = className.substring(10);
- }
- try {
- return Class.forName(className);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
- return objClass;
- }
- }
|