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实战开发篇 日志输出工具类的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot实战 之 接口日志篇

我的Android进阶之旅NDK开发之在C++代码中使用Android Log打印日志,打印出C++的函数耗时以及代码片段耗时详情

Android开发中有用工具之--Log工具类

solr分布式索引实战分片配置读取:工具类configUtil.java,读取配置代码片段,配置实例

android的日志Logger和Log比较,哪个好?

Android自动化测试实战 Java篇 主流工具 框架 脚本