安卓开发离不开记录log日志,封装了一份简单的日志工具类,具有设置日志总开关,是否写入文件,日志过滤器和自定义标签,锁定打印log的类、函数名及行号,初始化有可以使用init函数也可以使用建造者模式,具体使用参看单元测试。
站点
- 日志相关→LogUtils.java→Test
init : 初始化函数
getBuilder: 获取LogUtils建造者
v : Verbose日志
d : Debug日志
i : Info日志
w : Warn日志
e : Error日志
具体路线
import android.os.Environment;
import android.util.Log;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
*
* author: Blankj
* blog : http://blankj.com
* time : 2016/9/21
* desc : 日志相关工具类
*
*/
public class LogUtils {
private LogUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
private static boolean logSwitch = true;
private static boolean log2FileSwitch = false;
private static char logFilter = 'v';
private static String tag = "TAG";
private static String dir = null;
/**
* 初始化函数
* 与{@link #getBuilder()}两者选其一
*
* @param logSwitch 日志总开关
* @param log2FileSwitch 日志写入文件开关,设为true需添加权限 {@code }
* @param logFilter 输入日志类型有{@code v, d, i, w, e}
v代表输出所有信息,w则只输出警告...
* @param tag 标签
*/
public static void init(boolean logSwitch, boolean log2FileSwitch, char logFilter, String tag) {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
dir = Utils.getContext().getExternalCacheDir().getPath() + File.separator;
} else {
dir = Utils.getContext().getCacheDir().getPath() + File.separator;
}
LogUtils.logSwitch = logSwitch;
LogUtils.log2FileSwitch = log2FileSwitch;
LogUtils.logFilter = logFilter;
LogUtils.tag = tag;
}
/**
* 获取LogUtils建造者
* 与{@link #init(boolean, boolean, char, String)}两者选其一
*
* @return Builder对象
*/
public static Builder getBuilder() {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
dir = Utils.getContext().getExternalCacheDir().getPath() + File.separator + "log" + File.separator;
} else {
dir = Utils.getContext().getCacheDir().getPath() + File.separator + "log" + File.separator;
}
return new Builder();
}
public static class Builder {
private boolean logSwitch = true;
private boolean log2FileSwitch = false;
private char logFilter = 'v';
private String tag = "TAG";
public Builder setLogSwitch(boolean logSwitch) {
this.logSwitch = logSwitch;
return this;
}
public Builder setLog2FileSwitch(boolean log2FileSwitch) {
this.log2FileSwitch = log2FileSwitch;
return this;
}
public Builder setLogFilter(char logFilter) {
this.logFilter = logFilter;
return this;
}
public Builder setTag(String tag) {
this.tag = tag;
return this;
}
public void create() {
LogUtils.logSwitch = logSwitch;
LogUtils.log2FileSwitch = log2FileSwitch;
LogUtils.logFilter = logFilter;
LogUtils.tag = tag;
}
}
/**
* Verbose日志
*
* @param msg 消息
*/
public static void v(Object msg) {
log(tag, msg.toString(), null, 'i');
}
/**
* Verbose日志
*
* @param tag 标签
* @param msg 消息
*/
public static void v(String tag, Object msg) {
log(tag, msg.toString(), null, 'i');
}
/**
* Verbose日志
*
* @param tag 标签
* @param msg 消息
* @param tr 异常
*/
public static void v(String tag, Object msg, Throwable tr) {
log(tag, msg.toString(), tr, 'v');
}
/**
* Debug日志
*
* @param msg 消息
*/
public static void d(Object msg) {
log(tag, msg.toString(), null, 'd');
}
/**
* Debug日志
*
* @param tag 标签
* @param msg 消息
*/
public static void d(String tag, Object msg) {
log(tag, msg.toString(), null, 'd');
}
/**
* Debug日志
*
* @param tag 标签
* @param msg 消息
* @param tr 异常
*/
public static void d(String tag, Object msg, Throwable tr) {
log(tag, msg.toString(), tr, 'd');
}
/**
* Info日志
*
* @param msg 消息
*/
public static void i(Object msg) {
log(tag, msg.toString(), null, 'i');
}
/**
* Info日志
*
* @param tag 标签
* @param msg 消息
*/
public static void i(String tag, Object msg) {
log(tag, msg.toString(), null, 'i');
}
/**
* Info日志
*
* @param tag 标签
* @param msg 消息
* @param tr 异常
*/
public static void i(String tag, Object msg, Throwable tr) {
log(tag, msg.toString(), tr, 'i');
}
/**
* Warn日志
*
* @param msg 消息
*/
public static void w(Object msg) {
log(tag, msg.toString(), null, 'w');
}
/**
* Warn日志
*
* @param tag 标签
* @param msg 消息
*/
public static void w(String tag, Object msg) {
log(tag, msg.toString(), null, 'w');
}
/**
* Warn日志
*
* @param tag 标签
* @param msg 消息
* @param tr 异常
*/
public static void w(String tag, Object msg, Throwable tr) {
log(tag, msg.toString(), tr, 'w');
}
/**
* Error日志
*
* @param msg 消息
*/
public static void e(Object msg) {
log(tag, msg.toString(), null, 'e');
}
/**
* Error日志
*
* @param tag 标签
* @param msg 消息
*/
public static void e(String tag, Object msg) {
log(tag, msg.toString(), null, 'e');
}
/**
* Error日志
*
* @param tag 标签
* @param msg 消息
* @param tr 异常
*/
public static void e(String tag, Object msg, Throwable tr) {
log(tag, msg.toString(), tr, 'e');
}
/**
* 根据tag, msg和等级,输出日志
*
* @param tag 标签
* @param msg 消息
* @param tr 异常
* @param type 日志类型
*/
private static void log(String tag, String msg, Throwable tr, char type) {
if (logSwitch) {
if ('e' == type && ('e' == logFilter || 'v' == logFilter)) {
Log.e(generateTag(tag), msg, tr);
} else if ('w' == type && ('w' == logFilter || 'v' == logFilter)) {
Log.w(generateTag(tag), msg, tr);
} else if ('d' == type && ('d' == logFilter || 'v' == logFilter)) {
Log.d(generateTag(tag), msg, tr);
} else if ('i' == type && ('d' == logFilter || 'v' == logFilter)) {
Log.i(generateTag(tag), msg, tr);
}
if (log2FileSwitch) {
log2File(type, generateTag(tag), msg + '\n' + Log.getStackTraceString(tr));
}
}
}
/**
* 打开日志文件并写入日志
*
* @param type 日志类型
* @param tag 标签
* @param content 内容
**/
private synchronized static void log2File(final char type, final String tag, final String content) {
if (content == null) return;
Date now = new Date();
String date = new SimpleDateFormat("MM-dd", Locale.getDefault()).format(now);
final String fullPath = dir + date + ".txt";
if (!FileUtils.createOrExistsFile(fullPath)) return;
String time = new SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.getDefault()).format(now);
final String dateLogContent = time + ":" + type + ":" + tag + ":" + content + '\n';
new Thread(new Runnable() {
@Override
public void run() {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(fullPath, true));
bw.write(dateLogContent);
} catch (IOException e) {
e.printStackTrace();
} finally {
CloseUtils.closeIO(bw);
}
}
}).start();
}
/**
* 产生tag
*
* @return tag
*/
private static String generateTag(String tag) {
StackTraceElement[] stacks = Thread.currentThread().getStackTrace();
StackTraceElement caller = stacks[4];
String format = "Tag[" + tag + "] %s[%s, %d]";
String callerClazzName = caller.getClassName();
callerClazzName = callerClazzName.substring(callerClazzName.lastIndexOf(".") + 1);
return String.format(format, callerClazzName, caller.getMethodName(), caller.getLineNumber());
}
}
终点站
好了,终点站到了,如果对本次旅途满意的话,请给五星好评哦,毕竟老司机牺牲了很多时间才换来这么一份工具类,如果该工具类依赖其他工具类,都可以在我的Android开发人员不得不收集的代码(持续更新中)中找到。