background
This is a common class I found online a long time ago. I have forgotten the original link, but I think it is very useful and I have been using it all the time. I can write the logs into the file or locate the logs you printed on which class and line. The path to save to the file is android/data/your package name/files/ directory, and then we can happily find the problem.
import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; public class LogUtils { public static String customTagPrefix = "log"; // The prefix of the custom tag can be the author name private static final boolean isSaveLog = true; // Whether to save logs to the SD card private static String cacheDirPath; private LogUtils() { } // The type that allows printing of logs is true by default. If set to false, it will not be printed. public static boolean allowD = ; public static boolean allowE = ; public static boolean allowI = ; public static boolean allowV = ; public static boolean allowW = ; public static boolean allowWtf = ; // 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 = (); // Get the class name callerClazzName = ((".") + 1); tag = (tag, callerClazzName, (), ()); // Replace tag = (customTagPrefix) ? tag : customTagPrefix + ":" + tag; return tag; } /*** * The print console cannot display that long log problem * * @param msg */ public static void logE(String msg) { // The information is too long, print in segments if (!allowE) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); // Because the length of String is the number of characters not the number of bytes, in order to prevent too many Chinese characters, // Change the MAX byte print length of 4*1024 to 2001 characters int max_str_length = 2001 - (); // When greater than 4000 while (() > max_str_length) { // (tag, (0, max_str_length)); ((0, max_str_length)); msg = (max_str_length); } // The rest // (tag, msg); (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) { (tag, content); } else { (tag, content); } } public static void d(String content, Throwable tr) { if (!allowD) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content, tr); } else { (tag, content, tr); } } public static void e(String content) { if (!allowE) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content); } else { (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) { (tag, content, tr); } else { (tag, content, tr); } if (isSaveLog) { point(cacheDirPath, tag, ()); } } public static void e(Throwable tr) { if (!allowE) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, "", tr); } else { (tag, "", tr); } if (isSaveLog) { point(cacheDirPath, tag, ()); } } public static void i(String content) { if (!allowI) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content); } else { (tag, content); } } public static void i(String content, Throwable tr) { if (!allowI) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content, tr); } else { (tag, content, tr); } } public static void v(String content) { if (!allowV) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content); } else { (tag, content); } } public static void v(String content, Throwable tr) { if (!allowV) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content, tr); } else { (tag, content, tr); } } public static void w(String content) { if (!allowW) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content); } else { (tag, content); } } public static void w(String content, Throwable tr) { if (!allowW) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content, tr); } else { (tag, content, tr); } } public static void w(Throwable tr) { if (!allowW) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, tr); } else { (tag, tr); } } public static void wtf(String content) { if (!allowWtf) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content); } else { (tag, content); } } public static void wtf(String content, Throwable tr) { if (!allowWtf) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content, tr); } else { (tag, content, tr); } } public static void wtf(Throwable tr) { if (!allowWtf) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, tr); } else { (tag, tr); } } private static StackTraceElement getCallerStackTraceElement() { return ().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); ("yyyy"); path = path + (date) + "/"; ("MM"); path += (date) + "/"; ("dd"); path += (date) + ".log"; ("[yyyy-MM-dd HH:mm:ss]"); String time = (date); File file = new File(path); if (!()) createDipPath(path); BufferedWriter out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true))); (time + " " + tag + " " + msg + "\r\n"); } catch (Exception e) { (); } finally { try { if (out != null) { (); } } catch (IOException e) { (); } } } } /** * Create a file recursively based on file path * * @param file */ public static void createDipPath(String file) { String parentFile = (0, ("/")); File file1 = new File(file); File parent = new File(parentFile); if (!()) { (); try { (); ("The path to the log file is" + ()); } catch (IOException e) { (); } } } /** * 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) { (msg, args); String s = (); (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 (msg, args); } public static boolean isSDAva() { if (cacheDirPath == null) cacheDirPath = ().getExternalFilesDir("log").getAbsolutePath(); if (!(cacheDirPath)) { return true; } else { return false; } } }
Supplementary knowledge:Android log printing class LogUtils, which can locate class name, method name, and number of lines that occur incorrectly and save log files
In development, we often use the method of printing logs to debug our applications. In Java we often use method() to print logs on the console for our debugging. There is a special class Log in Android to implement the printing of logs under the Android system, which makes it more convenient for us to locate the problems in the program.
However, the Log class provided by Android is not very convenient for actual projects. When an error occurs in the program, what we most hope is that this Log class can help us locate which method of which class is, and even an error occurs in that line. This will bring great convenience to our debugging.
At the same time, we should also think that for the sake of application security, before the app is officially launched, we should turn off the function of printing logs in case others use Log to crack your application. When printing Log in production mode, the official mode turns off the function of printing logs. To achieve flexible closing and opening of Log, some encapsulation is also required on the native Log class.
There is another time when our program has problems and crashes, we hope to collect the causes of the exception for analysis, so we can save the log in a file and place it in the directory created by the SD card program. You can also upload the exception log log file in the background of the program to the server when the user is connected to the Internet, so that programmers can analyze and solve bugs.
Today I will share with you a very practical Log class LogUtils in the project. This class is extracted from xUtils, slightly modified, and has comments.
Example:
We call some methods in LogUtils in MainActivity, pay attention to the number of rows. 1
Then check if the log printed on the console is like the MainActivity call, the name of this class and the oncreate method name in the Log, which has the current number of lines; 2
I see the Log log in the above picture is very convenient for locating problems in the program, and it can be quickly located even if there is an exception. Then set the following Log type to false anywhere in the program, and the log will not be printed, which is quite convenient to use.
// The type that allows printing of logs is true by default. If set to false, it will not be printed. 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 ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * Log tool, similar. Tags are automatically generated, format: * customTagPrefix:(Line:lineNumber), * When customTagPrefix is empty, only output: (Line:lineNumber). */ public class LogUtils { public static String customTagPrefix = "finddreams"; // The prefix of the custom tag can be the author name private static final boolean isSaveLog = false; // Whether to save logs to the SD card public static final String ROOT = () .getPath() + "/finddreams/"; // The root directory in the SD card private static final String PATH_LOG_INFO = ROOT + "info/"; private LogUtils() { } // The type that allows printing of logs is true by default. If set to false, it will not be printed. 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 = (); // Get the class name callerClazzName = (callerClazzName .lastIndexOf(".") + 1); tag = (tag, callerClazzName, (), ()); // Replace tag = (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) { (tag, content); } else { (tag, content); } } public static void d(String content, Throwable tr) { if (!allowD) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content, tr); } else { (tag, content, tr); } } public static void e(String content) { if (!allowE) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content); } else { (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) { (tag, content, tr); } else { (tag, content, tr); } if (isSaveLog) { point(PATH_LOG_INFO, tag, ()); } } public static void i(String content) { if (!allowI) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content); } else { (tag, content); } } public static void i(String content, Throwable tr) { if (!allowI) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content, tr); } else { (tag, content, tr); } } public static void v(String content) { if (!allowV) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content); } else { (tag, content); } } public static void v(String content, Throwable tr) { if (!allowV) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content, tr); } else { (tag, content, tr); } } public static void w(String content) { if (!allowW) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content); } else { (tag, content); } } public static void w(String content, Throwable tr) { if (!allowW) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content, tr); } else { (tag, content, tr); } } public static void w(Throwable tr) { if (!allowW) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, tr); } else { (tag, tr); } } public static void wtf(String content) { if (!allowWtf) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content); } else { (tag, content); } } public static void wtf(String content, Throwable tr) { if (!allowWtf) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, content, tr); } else { (tag, content, tr); } } public static void wtf(Throwable tr) { if (!allowWtf) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { (tag, tr); } else { (tag, tr); } } private static StackTraceElement getCallerStackTraceElement() { return ().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); ("yyyy"); path = path + (date) + "/"; ("MM"); path += (date) + "/"; ("dd"); path += (date) + ".log"; ("[yyyy-MM-dd HH:mm:ss]"); String time = (date); File file = new File(path); if (!()) createDipPath(path); BufferedWriter out = null; try { out = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(file, true))); (time + " " + tag + " " + msg + "\r\n"); } catch (Exception e) { (); } finally { try { if (out != null) { (); } } catch (IOException e) { (); } } } } /** * Create a file recursively based on file path * * @param file */ public static void createDipPath(String file) { String parentFile = (0, ("/")); File file1 = new File(file); File parent = new File(parentFile); if (!()) { (); try { (); } catch (IOException e) { (); } } } /** * 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) { (msg, args); String s = (); (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 (msg, args); } public static boolean isSDAva() { if (().equals( Environment.MEDIA_MOUNTED) || ().exists()) { return true; } else { return false; } } }
The above android log file LogUtils example is all the content I share with you. I hope you can give you a reference and I hope you can support me more.