Android实战开发篇 日志输出工具类
Posted 彭老希
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android实战开发篇 日志输出工具类相关的知识,希望对你有一定的参考价值。
一、使用方式
//默认TAG
FaCaiCaiLog.v("Test");
//指定默认TAG
FaCaiCaiLog.initTAG("TAG2");
FaCaiCaiLog.d("Test2");
//指定TAG
FaCaiCaiLog.w("TAG","Test3");
//错误级别的,可以将日志写到文件,方便查看
FaCaiCaiLog.e("TAG","Crash");
//JSON输出
JSONObject jsonObject = null;
try{
jsonObject = new JSONObject();
jsonObject.put("name","xiaoming");
jsonObject.put("age","16");
}catch (Exception e){
e.printStackTrace();
}
String json = jsonObject.toString();
//打印json数据,会自动格式化
FaCaiCaiLog.json("TAG",json);
二、工具类
/**
* @author : Dumplings
* @version : v1.0.0
* @ClassName : FaCaiCaiLog.java
* @Function : 日志工具类
* @Description : 打印
* 1、线程名、
* 2、类名、
* 3、方法名、
* 4、源文件行数;
* 5、点击行数跳转到源码;
* 6、支持格式化json打印。
* @Idea :
* {@link }
* @Encourage :I try to learn something every day. It keeps me young.
* 我每天都在尝试学习新知识,这会让我保持青春活力。
* @date : 2021/5/12
*/
public class FaCaiCaiLog{
private static String TAG = "FaCaiCaiLog";
private static boolean isWriteLog2File = true;
private FaCaiCaiLog() {
/* cannot be instantiated */
throw new UnsupportedOperationException("FaCaiCaiLog cannot be instantiated");
}
/**
* 初始化
*
* @param logTag 全局日志tag
*/
public static void initTAG(String logTag) {
TAG = logTag;
}
public static void setWriteLog2File(boolean write) {
isWriteLog2File = write;
}
public static void v(String msg) {
if (AppBuildConfig.DEBUG) {
msg = createLog(msg);
Log.v(TAG, msg);
}
}
public static void d(String msg) {
if (AppBuildConfig.DEBUG) {
msg = createLog(msg);
Log.d(TAG, msg);
}
}
public static void i(String msg) {
if (AppBuildConfig.DEBUG) {
msg = createLog(msg);
Log.i(TAG, msg);
}
}
public static void w(String msg) {
if (AppBuildConfig.DEBUG) {
msg = createLog(msg);
Log.w(TAG, msg);
}
}
public static void e(String msg) {
if (AppBuildConfig.DEBUG) {
msg = createLog(msg);
Log.e(TAG, msg);
}
if (AppBuildConfig.DEBUG && isWriteLog2File) {
writeLog2File(TAG, msg);
}
}
public static void json(String json) {
if (AppBuildConfig.DEBUG) {
String msg = JsonFormatUtil.format(json);
json = createLog("\\n" + msg);
Log.i(TAG, json);
}
}
// 下面是传入自定义tag的函数
public static void v(String tag, String msg) {
if (AppBuildConfig.DEBUG) {
msg = createLog(msg);
Log.v(tag, msg);
}
}
public static void d(String tag, String msg) {
if (AppBuildConfig.DEBUG) {
msg = createLog(msg);
Log.d(tag, msg);
}
}
public static void i(String tag, String msg) {
if (AppBuildConfig.DEBUG) {
msg = createLog(msg);
Log.i(tag, msg);
}
}
public static void w(String tag, String msg) {
if (AppBuildConfig.DEBUG) {
msg = createLog(msg);
Log.w(tag, msg);
}
}
public static void e(String tag, String msg) {
if (AppBuildConfig.DEBUG) {
msg = createLog(msg);
Log.e(tag, msg);
}
if (AppBuildConfig.DEBUG && isWriteLog2File) {
writeLog2File(tag, msg);
}
}
public static void json(String tag, String json) {
if (AppBuildConfig.DEBUG) {
String msg = JsonFormatUtil.format(json);
json = createLog("\\n" + msg);
Log.i(tag, json);
}
}
private static String createLog(String log) {
// printThreadStackTrace();
StackTraceElement LogElement = Thread.currentThread().getStackTrace()[4];
String fullClassName = LogElement.getClassName();
String threadName = Thread.currentThread().getName();
String className = fullClassName.substring(fullClassName.lastIndexOf(".") + 1);
String methodName = LogElement.getMethodName();
String fileName = LogElement.getFileName();
int lineNumber = LogElement.getLineNumber();
StringBuffer buffer = new StringBuffer();
buffer.append("at ");//链接到源码
buffer.append("[");
buffer.append(threadName);
buffer.append(":");
buffer.append(className);
buffer.append(".");
buffer.append(methodName);
buffer.append("(");
buffer.append(fileName);
buffer.append(":");
buffer.append(lineNumber);
buffer.append(")");
buffer.append("] ");
buffer.append(log);
return buffer.toString();
}
public static void printThreadStackTrace() {
//通过线程栈帧元素获取相应信息
Log.i("FaCaiCaiLog", "sElements[0] = " + Thread.currentThread().getStackTrace()[0]);//VMStack
Log.i("FaCaiCaiLog", "sElements[1] = " + Thread.currentThread().getStackTrace()[1]);//Thread
Log.i("FaCaiCaiLog", "sElements[2] = " + Thread.currentThread().getStackTrace()[2]);//当前方法帧元素
Log.i("FaCaiCaiLog", "sElements[3] = " + Thread.currentThread().getStackTrace()[3]);//DishLog.x栈元素
Log.i("FaCaiCaiLog", "sElements[4] = " + Thread.currentThread().getStackTrace()[4]);//DishLog.x上层调用者
}
/**
* 写日志信息到文件,调试用,日志信息会自动换行.
* 需要写外部存储权限
*
* @param dir
* @param data
*/
public synchronized static void writeLog2File(String dir, String data) {
if (TextUtils.isEmpty(dir)) {
dir = TAG;
}
try {
String logPath = Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/MyApp/logs";
File logDir = new File(logPath + "/" + dir);
if (!logDir.exists()) {
if (!logDir.mkdirs()) {
return;
}
}
String fileName = new SimpleDateFormat("yyyyMMdd").format(new Date());
File file = new File(logDir, fileName + ".txt");
if (file.exists()) {
if (file.length() > 200 * 1024) {
file.delete();
if (!file.createNewFile()) {
return;
}
}
} else {
if (!file.createNewFile()) {
return;
}
}
StringBuilder buffer = new StringBuilder();
SimpleDateFormat sDateFormatYMD = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String dateString = sDateFormatYMD.format(new Date(System.currentTimeMillis()));
buffer.append(dateString).append(" ").append(data).append("\\r\\n");
RandomAccessFile raf = new RandomAccessFile(file, "rw");// "rw" 读写权限
raf.seek(file.length());
raf.write(buffer.toString().getBytes());
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
三、JSON格式化工具类
/**
*
* @author : Dumplings
* @version : v1.0.0
* @ClassName : JsonFormatUtil.java
* @Function : JSON格式化工具类
* @Description :
* @Idea :
* {@link }
* @Encourage :I try to learn something every day. It keeps me young.
* 我每天都在尝试学习新知识,这会让我保持青春活力。
* @date : 2021/5/12
*/
public class JsonFormatUtil {
/**
* 默认每次缩进两个空格
*/
private static final String empty = " ";
public static String format(String json) {
try {
int empty = 0;
char[] chs = json.toCharArray();
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < chs.length; ) {
//若是双引号,则为字符串,下面if语句会处理该字符串
if (chs[i] == '\\"') {
stringBuilder.append(chs[i]);
i++;
//查找字符串结束位置
for (; i < chs.length; ) {
//如果当前字符是双引号,且前面有连续的偶数个\\,说明字符串结束
if (chs[i] == '\\"' && isDoubleSerialBackslash(chs, i - 1)) {
stringBuilder.append(chs[i]);
i++;
break;
} else {
stringBuilder.append(chs[i]);
i++;
}
}
} else if (chs[i] == ',') {
stringBuilder.append(',').append('\\n').append(getEmpty(empty));
i++;
} else if (chs[i] == '{' || chs[i] == '[') {
empty++;
stringBuilder.append(chs[i]).append('\\n').append(getEmpty(empty));
i++;
} else if (chs[i] == '}' || chs[i] == ']') {
empty--;
stringBuilder.append('\\n').append(getEmpty(empty)).append(chs[i]);
i++;
} else {
stringBuilder.append(chs[i]);
i++;
}
}
return stringBuilder.toString();
} catch (Exception e) {
e.printStackTrace();
return json;
}
}
/**
* 是否有两个连续的反斜杠\\
*
* @param chs
* @param i
* @return
*/
private static boolean isDoubleSerialBackslash(char[] chs, int i) {
int count = 0;
for (int j = i; j > -1; j--) {
if (chs[j] == '\\\\') {
count++;
} else {
return count % 2 == 0;
}
}
return count % 2 == 0;
}
/**
* 缩进
*
* @param count
* @return
*/
private static String getEmpty(int count) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < count; i++) {
stringBuilder.append(empty);
}
return stringBuilder.toString();
}
}
四、应用程式建立设定
/**
* @author : Dumplings
* @version : v1.0.0
* @ClassName : AppBuildConfig.java
* @Function :
* @Description :
* @Idea :
* {@link }
* @Encourage :I try to learn something every day. It keeps me young.
* 我每天都在尝试学习新知识,这会让我保持青春活力。
* @date : 2021/5/12
*/
public class AppBuildConfig {
public static final boolean DEBUG = true;
}
以上是关于Android实战开发篇 日志输出工具类的主要内容,如果未能解决你的问题,请参考以下文章
我的Android进阶之旅NDK开发之在C++代码中使用Android Log打印日志,打印出C++的函数耗时以及代码片段耗时详情