Android 日志工具
目标实现功能
- 打印日志到控制台和文件中
- 日志支持在logcat 窗口 有链接跳转到对应的位置,文件中就直接拷贝内容到logcat 窗口 也支持链接
- 文件支持设置文件大小和最大数量
使用方法:
LogUtil.d("process------------>");
一共有两个文件LogUtil和LogFileUtil,代码如下:
import android.util.Log;
/**
* 输出各种级别的log到控制台
* msg字符长度不受限制,默认的Log是受限制的,超过的部分不输出
* 输出的log头有链接,可以点击链接到执行代码文件位置
* 可以直接输出msg,使用默认Tag
* 支持设置 LEVEL,小于LEVEL级别以下不再打印log
*/
public class LogUtil {
private static final String TAG = "LogUtil";
public static int LEVEL = Log.VERBOSE;
public static void v(String TAG, String msg) {
if (LEVEL <= Log.VERBOSE) {
logWithLink(Log.VERBOSE, TAG, msg);
}
}
public static void d(String TAG, String msg) {
if (LEVEL <= Log.DEBUG) {
logWithLink(Log.DEBUG, TAG, msg);
}
}
public static void i(String TAG, String msg) {
if (LEVEL <= Log.INFO) {
logWithLink(Log.INFO, TAG, msg);
}
}
public static void w(String TAG, String msg) {
if (LEVEL <= Log.WARN) {
logWithLink(Log.WARN, TAG, msg);
}
}
public static void e(String TAG, String msg) {
if (LEVEL <= Log.ERROR) {
logWithLink(Log.ERROR, TAG, msg);
}
}
public static void v(String msg) {
if (LEVEL <= Log.VERBOSE) {
logWithLink(Log.VERBOSE, TAG, msg);
}
}
public static void d(String msg) {
if (LEVEL <= Log.DEBUG) {
logWithLink(Log.DEBUG, TAG, msg);
}
}
public static void i(String msg) {
if (LEVEL <= Log.INFO) {
logWithLink(Log.INFO, TAG, msg);
}
}
public static void w(String msg) {
if (LEVEL <= Log.WARN) {
logWithLink(Log.WARN, TAG, msg);
}
}
public static void e(String msg) {
if (LEVEL <= Log.ERROR) {
logWithLink(Log.ERROR, TAG, msg);
}
}
//Log输出的最大长度
private static int LOG_MAX_LENGTH = 2000;//2000
/**
* 循环打印log,解决msg过长不打印问题
*/
private static void LogWrapperLoop(int logPriority, String TAG, String msg) {
int msgLength = msg.length();
/**
* adb lgh=3
* ^
* | index=1
* print a
*/
int index = 0;//输出字符的位置
while (index < msgLength) {
if (index LOG_MAX_LENGTH > msgLength) {
LogWrapper(logPriority, TAG, msg.substring(index, msgLength));
} else {
LogWrapper(logPriority, TAG, msg.substring(index, index LOG_MAX_LENGTH));
}
index = LOG_MAX_LENGTH;
}
}
private static void LogWrapper(int logPriority, String TAG, String msg) {
switch (logPriority) {
case Log.VERBOSE:
LogFileUtil.v(TAG, msg);
Log.v(TAG, msg);
break;
case Log.DEBUG:
LogFileUtil.d(TAG, msg);
Log.d(TAG, msg);
break;
case Log.INFO:
LogFileUtil.i(TAG, msg);
Log.i(TAG, msg);
break;
case Log.WARN:
LogFileUtil.w(TAG, msg);
Log.w(TAG, msg);
break;
case Log.ERROR:
LogFileUtil.e(TAG, msg);
Log.e(TAG, msg);
break;
case Log.ASSERT:
break;
default:
break;
}
}
/**
* 带有链接的log打印
*/
private static void logWithLink(int logPriority, String TAG, String msg) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
int index = 4;
String className = stackTrace[index].getFileName();
String methodName = stackTrace[index].getMethodName();
int lineNumber = stackTrace[index].getLineNumber();
methodName = methodName.substring(0, 1).toUpperCase() methodName.substring(1);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("[ (").append(className).append(":").append(lineNumber).append(")#").append(methodName).append(" ] ");
stringBuilder.append(msg);
String logStr = stringBuilder.toString();
LogWrapperLoop(logPriority, TAG, logStr);
}
}
import android.util.Log;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.concurrent.Executors;
/**
* 将日志打印到文件:
* <p>
* 支持设置文件最大大小LOG_SIZE_MAX KB,超过大小重新创建文件(由于文件名是以毫秒为维度理论不会重复)
* 支持文件总个数LOG_FILE_TOTAL,超过总个数删除最先创建的文件
* 支持设置日志文件输出目录LOG_FILE_PRINT_DIR
*/
public class LogFileUtil {
// 日志文件总数
private static final int LOG_FILE_TOTAL = 10;
// 单日志文件大小上限 KB
private static final long LOG_SIZE_MAX = 5 * 1024;
// 日志文件输出文件夹
private static final String LOG_FILE_PRINT_DIR = "/sdcard/MyProject/log/info/";
// 文件名格式
private static final SimpleDateFormat FILE_NAME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss-SSS");
//创建一个可重用固定线程数的线程池
private static java.util.concurrent.ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
public static final void v(String TAG, String msg) {
printLog("VERBOSE", TAG, msg);
}
public static final void d(String TAG, String msg) {
printLog("DEBUG", TAG, msg);
}
public static final void i(String TAG, String msg) {
printLog("INFO ", TAG, msg);
}
public static final void w(String TAG, String msg) {
printLog("WARN ", TAG, msg);
}
public static final void e(String TAG, String msg) {
printLog("ERROR", TAG, msg);
}
private static void printLog(final String level, final String TAG, final String msg) {
singleThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
FileWriter fileWriter = new FileWriter(getFile(), true);
fileWriter.write(formatLog(level, TAG, msg));
fileWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
//格式化日志
private static String formatLog(String level, String TAG, String msg) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
StringBuilder builder = new StringBuilder();
builder.append(dateFormat.format(new Date(System.currentTimeMillis())) " ");
builder.append("[" level "] ");
builder.append("[" TAG "] ");
builder.append(msg);
builder.append("\n");
return builder.toString();
}
// 获取需要输出的日志文件
private static File getFile() {
// 确认文件夹是否存在
File fileDir = new File(LOG_FILE_PRINT_DIR);
if (!fileDir.exists()) {
fileDir.mkdirs();
}
// 获取文件夹下的日志文件
File[] fileList = fileDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".log");
}
});
int fileCount = fileList == null ? 0 : fileList.length;
// 没有日志文件时,直接创建新文件
if (fileCount == 0) {
return createLogFile();
}
// 只有一个日志文件时
if (fileCount == 1) {
return isCreateLogFile(fileList[0]);
}
// 对日志排序,排序结果为升序
Arrays.sort(fileList, new Comparator<File>() {
@Override
public int compare(File file1, File file2) {
String file1Name = "";
String file2Name = "";
try {
file1Name = file1.getName().split(".log")[0];
file2Name = file2.getName().split(".log")[0];
Date dateFile1 = FILE_NAME_FORMAT.parse(file1Name);
Date dateFile2 = FILE_NAME_FORMAT.parse(file2Name);
return dateFile1.getTime() < dateFile2.getTime() ? -1 : 1;
} catch (Exception e) {
Log.i("LogUtil", "file1Name:" file1Name ", file2Name:" file2Name);
e.printStackTrace();
}
return 0;
}
});
File lastFile = fileList[fileCount - 1];
// 日志文件未超过最大控制个数
if (fileCount < LOG_FILE_TOTAL) {
return isCreateLogFile(lastFile);
}
if (sizeOf(lastFile) >= LOG_SIZE_MAX) {
// 删除时间最早的一个文件
fileList[0].delete();
}
return isCreateLogFile(lastFile);
}
// 确认是否需要创建新日志文件
private static File isCreateLogFile(File file) {
// 超过日志文件大小上限,需要创建新日志文件
if (sizeOf(file) >= LOG_SIZE_MAX) {
return createLogFile();
}
return file;
}
// 创建一个新的日志文件
private static File createLogFile() {
return new File(LOG_FILE_PRINT_DIR FILE_NAME_FORMAT.format(new Date(System.currentTimeMillis())) ".log");
}
// 计算文件大小,返回单位 KB
private static long sizeOf(File file) {
long length = file.length();
return length / 1024;
}
}
赞 (0)