android Log File LogUtils Instance
- 2021-12-05 07:23:32
- OfStack
Background
This is a long time ago in the network to find a common class, has forgotten the original link, but feel very good to use 1 straight in use, can log written to file inside can also locate you in which class which 1 line print log, save to the file path is android/data/your package name/files/directory, and then we can find problems happily
import android.text.TextUtils;
import android.util.Log;
import com.smartlink.suixing.App;
import com.smartlink.suixing.BuildConfig;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Formatter;
import java.util.Locale;
public class LogUtils {
public static String customTagPrefix = "log"; // Customize Tag The prefix of, which can be the author name
private static final boolean isSaveLog = true; // Do you want to save the log to SD Card
private static String cacheDirPath;
private LogUtils() {
}
// The type of log allowed to be printed, the default is true Is set to false Do not print
public static boolean allowD = BuildConfig.DEBUG;
public static boolean allowE = BuildConfig.DEBUG;
public static boolean allowI = BuildConfig.DEBUG;
public static boolean allowV = BuildConfig.DEBUG;
public static boolean allowW = BuildConfig.DEBUG;
public static boolean allowWtf = BuildConfig.DEBUG;
// public static boolean allowD = true;
// public static boolean allowE = true;
// public static boolean allowI = true;
// public static boolean allowV = true;
// public static boolean allowW = true;
// public static boolean allowWtf = true;
private static String generateTag(StackTraceElement caller) {
String tag = "%s.%s(Line:%d)"; // Placeholder
String callerClazzName = caller.getClassName(); // Get to the class name
callerClazzName = callerClazzName.substring(callerClazzName.lastIndexOf(".") + 1);
tag = String.format(tag, callerClazzName, caller.getMethodName(), caller.getLineNumber()); // Replace
tag = TextUtils.isEmpty(customTagPrefix) ? tag : customTagPrefix + ":" + tag;
return tag;
}
/***
* The print console can't display that long log problem
*
* @param msg
*/
public static void logE(String msg) { // The message is too long , Sectional printing
if (!allowE) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
// Because String Adj. length The number of characters is not the number of bytes, so in order to prevent too many Chinese characters,
// Put 4*1024 Adj. MAX Byte print length changed to 2001 Number of characters
int max_str_length = 2001 - tag.length();
// Greater than 4000 Hour
while (msg.length() > max_str_length) {
// Log.e(tag, msg.substring(0, max_str_length));
LogUtils.e(msg.substring(0, max_str_length));
msg = msg.substring(max_str_length);
}
// The remainder
// Log.e(tag, msg);
LogUtils.e(msg);
}
/**
* Custom logger
*/
public static CustomLogger customLogger;
public interface CustomLogger {
void d(String tag, String content);
void d(String tag, String content, Throwable tr);
void e(String tag, String content);
void e(String tag, String content, Throwable tr);
void i(String tag, String content);
void i(String tag, String content, Throwable tr);
void v(String tag, String content);
void v(String tag, String content, Throwable tr);
void w(String tag, String content);
void w(String tag, String content, Throwable tr);
void w(String tag, Throwable tr);
void wtf(String tag, String content);
void wtf(String tag, String content, Throwable tr);
void wtf(String tag, Throwable tr);
}
public static void d(String content) {
if (!allowD) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.d(tag, content);
} else {
Log.d(tag, content);
}
}
public static void d(String content, Throwable tr) {
if (!allowD) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.d(tag, content, tr);
} else {
Log.d(tag, content, tr);
}
}
public static void e(String content) {
if (!allowE) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.e(tag, content);
} else {
Log.e(tag, content);
}
if (isSaveLog) {
point(cacheDirPath, tag, content);
}
}
public static void e(String content, Throwable tr) {
if (!allowE) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.e(tag, content, tr);
} else {
Log.e(tag, content, tr);
}
if (isSaveLog) {
point(cacheDirPath, tag, tr.getMessage());
}
}
public static void e(Throwable tr) {
if (!allowE) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.e(tag, "", tr);
} else {
Log.e(tag, "", tr);
}
if (isSaveLog) {
point(cacheDirPath, tag, tr.getMessage());
}
}
public static void i(String content) {
if (!allowI) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.i(tag, content);
} else {
Log.i(tag, content);
}
}
public static void i(String content, Throwable tr) {
if (!allowI) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.i(tag, content, tr);
} else {
Log.i(tag, content, tr);
}
}
public static void v(String content) {
if (!allowV) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.v(tag, content);
} else {
Log.v(tag, content);
}
}
public static void v(String content, Throwable tr) {
if (!allowV) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.v(tag, content, tr);
} else {
Log.v(tag, content, tr);
}
}
public static void w(String content) {
if (!allowW) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.w(tag, content);
} else {
Log.w(tag, content);
}
}
public static void w(String content, Throwable tr) {
if (!allowW) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.w(tag, content, tr);
} else {
Log.w(tag, content, tr);
}
}
public static void w(Throwable tr) {
if (!allowW) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.w(tag, tr);
} else {
Log.w(tag, tr);
}
}
public static void wtf(String content) {
if (!allowWtf) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.wtf(tag, content);
} else {
Log.wtf(tag, content);
}
}
public static void wtf(String content, Throwable tr) {
if (!allowWtf) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.wtf(tag, content, tr);
} else {
Log.wtf(tag, content, tr);
}
}
public static void wtf(Throwable tr) {
if (!allowWtf) return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.wtf(tag, tr);
} else {
Log.wtf(tag, tr);
}
}
private static StackTraceElement getCallerStackTraceElement() {
return Thread.currentThread().getStackTrace()[4];
}
public static void point(String path, String tag, String msg) {
if (isSDAva()) {
path = cacheDirPath;
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("", Locale.SIMPLIFIED_CHINESE);
dateFormat.applyPattern("yyyy");
path = path + dateFormat.format(date) + "/";
dateFormat.applyPattern("MM");
path += dateFormat.format(date) + "/";
dateFormat.applyPattern("dd");
path += dateFormat.format(date) + ".log";
dateFormat.applyPattern("[yyyy-MM-dd HH:mm:ss]");
String time = dateFormat.format(date);
File file = new File(path);
if (!file.exists()) createDipPath(path);
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true)));
out.write(time + " " + tag + " " + msg + "\r\n");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* According to the file path Recursive file creation
*
* @param file
*/
public static void createDipPath(String file) {
String parentFile = file.substring(0, file.lastIndexOf("/"));
File file1 = new File(file);
File parent = new File(parentFile);
if (!file1.exists()) {
parent.mkdirs();
try {
file1.createNewFile();
LogUtils.e(" The path to the log file is " + file1.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* A little trick to reuse a formatter in the same thread
*/
private static class ReusableFormatter {
private Formatter formatter;
private StringBuilder builder;
public ReusableFormatter() {
builder = new StringBuilder();
formatter = new Formatter(builder);
}
public String format(String msg, Object... args) {
formatter.format(msg, args);
String s = builder.toString();
builder.setLength(0);
return s;
}
}
private static final ThreadLocal<ReusableFormatter> thread_local_formatter = new ThreadLocal<ReusableFormatter>() {
protected ReusableFormatter initialValue() {
return new ReusableFormatter();
}
};
public static String format(String msg, Object... args) {
ReusableFormatter formatter = thread_local_formatter.get();
return formatter.format(msg, args);
}
public static boolean isSDAva() {
if (cacheDirPath == null) cacheDirPath = App.getAppContext().getExternalFilesDir("log").getAbsolutePath();
if (!TextUtils.isEmpty(cacheDirPath)) {
return true;
} else {
return false;
}
}
}
Additional knowledge: Android log printing class LogUtils can navigate the class name, method name and the number of lines with errors and save the log file
In development, we often debug our application by printing log. In Java we often use the methods System. out. println () to print logs on the console for our debugging. In Android, there is a special class Log to realize the log printing under Android system, which is more convenient for us to locate the program where there are problems.
However, the Log class officially provided by Android is not very convenient in actual project use. When an error occurs in the program, what we hope most is that this Log class can help us locate which method of which class, and even then there is an error in that line. This can bring great convenience to our debugging.
At the same time, we should also think that for the sake of application security, before app is officially launched, we should turn off the function of printing logs to prevent others from cracking your application through Log. When printing Log in production mode, the function of printing log is turned off in formal mode. To close and open Log flexibly, it is also necessary to encapsulate it on the native Log class.
There is another time, when our program crashes due to problems, we hope to collect the causes of exceptions for analysis, so we can save the Log log to a file and put it in the directory created by the SD card program. You can also upload the abnormal Log log file to the server in the background of the program when the user is networked, which is convenient for programmers to analyze and solve bug.
Today, I will share with you a very practical Log class LogUtils, this class is extracted from xUtils, slightly modified, there are comments.
Example:
We call a few methods in LogUtils in MainActivity, paying attention to the number of lines. 1
Then see if the log printed by the console is like that called by MainActivity. Log has the name of this class and the method name of oncreate, and the current number of lines; 2
See the Log log in the above figure is not very convenient to locate the problems in the program, and the exception can be located quickly. Then set the following Log type to false anywhere in the program, so it will not print logs, which is quite convenient to use.
// The type of log allowed to be printed, the default is true Is set to false Do not print
public static boolean allowD = true;
public static boolean allowE = true;
public static boolean allowI = true;
public static boolean allowV = true;
public static boolean allowW = true;
public static boolean allowWtf = true;
The code is posted below:
package com.finddreams.log;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Formatter;
import java.util.Locale;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
/**
* Log Tools, similar to android.util.Log . tag Automatically generated, formatted :
* customTagPrefix:className.methodName(Line:lineNumber),
* customTagPrefix Output only when empty: className.methodName(Line:lineNumber) .
*/
public class LogUtils {
public static String customTagPrefix = "finddreams"; // Customize Tag The prefix of, which can be the author name
private static final boolean isSaveLog = false; // Do you want to save the log to SD Card
public static final String ROOT = Environment.getExternalStorageDirectory()
.getPath() + "/finddreams/"; // SD Root directory in card
private static final String PATH_LOG_INFO = ROOT + "info/";
private LogUtils() {
}
// The type of log allowed to be printed, the default is true Is set to false Do not print
public static boolean allowD = true;
public static boolean allowE = true;
public static boolean allowI = true;
public static boolean allowV = true;
public static boolean allowW = true;
public static boolean allowWtf = true;
private static String generateTag(StackTraceElement caller) {
String tag = "%s.%s(Line:%d)"; // Placeholder
String callerClazzName = caller.getClassName(); // Get to the class name
callerClazzName = callerClazzName.substring(callerClazzName
.lastIndexOf(".") + 1);
tag = String.format(tag, callerClazzName, caller.getMethodName(),
caller.getLineNumber()); // Replace
tag = TextUtils.isEmpty(customTagPrefix) ? tag : customTagPrefix + ":"
+ tag;
return tag;
}
/**
* Custom logger
*/
public static CustomLogger customLogger;
public interface CustomLogger {
void d(String tag, String content);
void d(String tag, String content, Throwable tr);
void e(String tag, String content);
void e(String tag, String content, Throwable tr);
void i(String tag, String content);
void i(String tag, String content, Throwable tr);
void v(String tag, String content);
void v(String tag, String content, Throwable tr);
void w(String tag, String content);
void w(String tag, String content, Throwable tr);
void w(String tag, Throwable tr);
void wtf(String tag, String content);
void wtf(String tag, String content, Throwable tr);
void wtf(String tag, Throwable tr);
}
public static void d(String content) {
if (!allowD)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.d(tag, content);
} else {
Log.d(tag, content);
}
}
public static void d(String content, Throwable tr) {
if (!allowD)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.d(tag, content, tr);
} else {
Log.d(tag, content, tr);
}
}
public static void e(String content) {
if (!allowE)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.e(tag, content);
} else {
Log.e(tag, content);
}
if (isSaveLog) {
point(PATH_LOG_INFO, tag, content);
}
}
public static void e(String content, Throwable tr) {
if (!allowE)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.e(tag, content, tr);
} else {
Log.e(tag, content, tr);
}
if (isSaveLog) {
point(PATH_LOG_INFO, tag, tr.getMessage());
}
}
public static void i(String content) {
if (!allowI)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.i(tag, content);
} else {
Log.i(tag, content);
}
}
public static void i(String content, Throwable tr) {
if (!allowI)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.i(tag, content, tr);
} else {
Log.i(tag, content, tr);
}
}
public static void v(String content) {
if (!allowV)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.v(tag, content);
} else {
Log.v(tag, content);
}
}
public static void v(String content, Throwable tr) {
if (!allowV)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.v(tag, content, tr);
} else {
Log.v(tag, content, tr);
}
}
public static void w(String content) {
if (!allowW)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.w(tag, content);
} else {
Log.w(tag, content);
}
}
public static void w(String content, Throwable tr) {
if (!allowW)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.w(tag, content, tr);
} else {
Log.w(tag, content, tr);
}
}
public static void w(Throwable tr) {
if (!allowW)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.w(tag, tr);
} else {
Log.w(tag, tr);
}
}
public static void wtf(String content) {
if (!allowWtf)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.wtf(tag, content);
} else {
Log.wtf(tag, content);
}
}
public static void wtf(String content, Throwable tr) {
if (!allowWtf)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.wtf(tag, content, tr);
} else {
Log.wtf(tag, content, tr);
}
}
public static void wtf(Throwable tr) {
if (!allowWtf)
return;
StackTraceElement caller = getCallerStackTraceElement();
String tag = generateTag(caller);
if (customLogger != null) {
customLogger.wtf(tag, tr);
} else {
Log.wtf(tag, tr);
}
}
private static StackTraceElement getCallerStackTraceElement() {
return Thread.currentThread().getStackTrace()[4];
}
public static void point(String path, String tag, String msg) {
if (isSDAva()) {
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("",
Locale.SIMPLIFIED_CHINESE);
dateFormat.applyPattern("yyyy");
path = path + dateFormat.format(date) + "/";
dateFormat.applyPattern("MM");
path += dateFormat.format(date) + "/";
dateFormat.applyPattern("dd");
path += dateFormat.format(date) + ".log";
dateFormat.applyPattern("[yyyy-MM-dd HH:mm:ss]");
String time = dateFormat.format(date);
File file = new File(path);
if (!file.exists())
createDipPath(path);
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(file, true)));
out.write(time + " " + tag + " " + msg + "\r\n");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* According to the file path Recursive file creation
*
* @param file
*/
public static void createDipPath(String file) {
String parentFile = file.substring(0, file.lastIndexOf("/"));
File file1 = new File(file);
File parent = new File(parentFile);
if (!file1.exists()) {
parent.mkdirs();
try {
file1.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* A little trick to reuse a formatter in the same thread
*/
private static class ReusableFormatter {
private Formatter formatter;
private StringBuilder builder;
public ReusableFormatter() {
builder = new StringBuilder();
formatter = new Formatter(builder);
}
public String format(String msg, Object... args) {
formatter.format(msg, args);
String s = builder.toString();
builder.setLength(0);
return s;
}
}
private static final ThreadLocal<ReusableFormatter> thread_local_formatter = new ThreadLocal<ReusableFormatter>() {
protected ReusableFormatter initialValue() {
return new ReusableFormatter();
}
};
public static String format(String msg, Object... args) {
ReusableFormatter formatter = thread_local_formatter.get();
return formatter.format(msg, args);
}
public static boolean isSDAva() {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)
|| Environment.getExternalStorageDirectory().exists()) {
return true;
} else {
return false;
}
}
}