import android.content.Context;
import android.os.Environment;
import android.util.Log;
import com.hjq.toast.ToastUtils;
import com.mlibs.library.common.utils.IOUtils;
import com.mlibs.library.common.utils.StringUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* 错误日志打印工具,带定位功能(输出调用处类型名、方法名、行,点击可追踪到)
*/
public class XLog {
/** 是否打印日志 */
public static boolean isConsoleLog = true;
public static final String TEST_INFO = "";
private static int stepNumber = 0;
public static String TAG = "调试信息";
private static int logsegmentSize = 3072;//最长为4*1024设置为
/**
* 打印错误信息
*
* @param msg 错误信息
*/
public static void tipInfo(String msg) {
if (isConsoleLog && BuildConfig.DEBUG) {
ToastUtils.show(StringUtil.defaultIfBlank(msg, "null"));
}
}
/**
* 打印错误信息
*
* @param msg 错误信息
*/
public static void tipDialog(Context context, String msg) {
if (isConsoleLog && BuildConfig.DEBUG) {
DialogUtil.showSimpleDialog(context, msg);
}
}
/**
* 普通日志输出
*
* @param localTag tag
* @param logMsg info
*/
public static void commonLog(String localTag, String logMsg) {
if (isConsoleLog) {
if (logMsg.length() > logsegmentSize) {
int count = logMsg.length() / logsegmentSize;
for (int i = 0; i < count; i++) {
if (logMsg.length() > logsegmentSize) {
Log.v(localTag, logMsg.substring(0, logsegmentSize));
logMsg = logMsg.substring(logsegmentSize);
}
}
}
Log.v(localTag, logMsg);
}
}
private static String isEmpty(Object msg) {
if (msg == null) {
return "日志调用处为null";
} else if (strNull.equals(msg)) {
return "日志调用处为字符串null";
} else if ("".equals(msg)) {
return "日志调用处为空字符串\"\"";
}
return msg.toString();
}
/**
* 显示异常信息
*
* @param e 异常信息
*/
public static String getExceptionInfo(Throwable e) {
return Log.getStackTraceString(e);
}
/**
* 显示异常信息
*
* @param e 异常信息
*/
public static void printExceptionInfo(Throwable e) {
if (isConsoleLog) {
Log.e(TAG, "抛异常了" + Log.getStackTraceString(e));
// printMsgToFile(getStackTrace(), "输出异常日志", Log.getStackTraceString(e));
}
}
/**
* 提示信息
*
* @param msg 错误信息
*/
public static void file(String msg) {
if (!isConsoleLog) return;
file("调试信息", msg);
}
/**
* 打印错误信息
*
* @param msg 错误信息
*/
public static void file(String fileName, String msg) {
if (!isConsoleLog) return;
String content = "-----------------" + DateUtil.formatCurrentDate(DateUtil.REGEX_DATE_TIME) + "-------------------\n\n" + msg + "\n\n\n";
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
// String appCrashPath = Environment.getExternalStorageDirectory().getPath() + File.separator + "crash" + File.separator;
String appCrashPath = Constant.APP_CRASH_PATH;
if (new File(appCrashPath).mkdirs()) {
Log.e(TAG, "创建日志文件夹失败!!!");
return;
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(appCrashPath + fileName + ".log", true);
fos.write(content.getBytes());
} catch (Exception e) {
printExceptionInfo(e);
} finally {
IOUtils.close(fos);
}
}
}
/**
* 打印步骤
*/
public static void showStepLogInfo() {
if (!isConsoleLog) return;
showLogs("", "步骤" + stepNumber++);
}
/**
* 打印错误信息
*/
public static void showArgsInfo(Object... args) {
if (!isConsoleLog) return;
showLogs("", Arrays.toString(args));
}
/**
* 调用处子类方法所在位置
*
* @param msg smg
*/
public static void getChildLog(String msg) {
if (!isConsoleLog) {
return;
}
StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[4];
String stackTraceMsgArr = stackTraceElement.toString();
Log.i(TAG, stackTraceMsgArr.substring(stackTraceMsgArr.indexOf("(")) + "#" + stackTraceElement.getMethodName() + " msg:" + msg);
}
/**
* 获取StackTraceElement对象-----当前调用XLog.showLogInfo()处的类信息(类名、方法名、行等)
* 堆栈跟踪元素:当前调用Log.showLogInfo()处的类信息(类名、方法名、行等)
*
* @return .
*/
private static String getStackTraceStr() {
/*简化版:Thread.currentThread().getStackTrace()[4].toString().substring(23).replaceFirst("\\.", "#")*/
StackTraceElement trace = Thread.currentThread().getStackTrace()[5];
return "(" + trace.getFileName() + ":" + trace.getLineNumber() + ")" + "#" + trace.getMethodName() + " ";
}
/**
* 打印日志
*
* @param msg .
*/
private static void showLogs(String tag, String msg) {
msg = msg.replace("(", "(").replace(")", ")");
if (msg.length() > logsegmentSize) {
while (msg.length() > logsegmentSize) {
Log.i(TAG, getStackTraceStr() + tag + msg);
msg = msg.substring(logsegmentSize);
}
}
Log.i(TAG, getStackTraceStr() + tag + msg);
}
private static String joPrefix = "{";
private static String joSuffix = "}";
private static String strNull = "null";
public static void printJson(String headString, String jsonStr) {
String tag = headString;
String s = "@";
if (headString.contains(s)) {
tag = headString.substring(0, headString.indexOf(s));
headString = headString.substring(headString.indexOf(s) + 1);
}
if (isConsoleLog) {
if (jsonStr == null) {
showLogs("", "调用处为null");
} else {
if (strNull.equals(jsonStr)) {
showLogs("", "调用处为null字符串");
} else {
String message;
try {
if (jsonStr.startsWith(joPrefix)) {
JSONObject jsonObject = new JSONObject(jsonStr);
//最重要的方法,就一行,返回格式化的json字符串,其中的数字4是缩进字符数
message = jsonObject.toString(4);
} else {
if (jsonStr.startsWith("[")) {
JSONArray jsonArray = new JSONArray(jsonStr);
message = jsonArray.toString(4);
} else {
message = jsonStr;
}
}
} catch (JSONException e) {
message = jsonStr;
}
printLine(tag, true);
message = headString + System.getProperty("line.separator") + message;
String[] lines = message.split(System.getProperty("line.separator"));
for (String line : lines) {
if (line.length() <= logsegmentSize) {
Log.d(tag, "║ " + line);
} else {
while (line.length() > logsegmentSize) {
Log.d(tag, "║ " + line);
String msgs = line.substring(0, logsegmentSize);
line = line.replace(msgs, "");
}
Log.d(tag, "║ " + line);
}
}
printLine(tag, false);
}
}
}
}
private static void printLine(String tag, boolean isTop) {
if (isTop) {
Log.d(tag, "╔═══════════════════════════════════════════════════════════════════════════════════════");
} else {
Log.d(tag, "╚═══════════════════════════════════════════════════════════════════════════════════════");
}
}
}