错误日志打印工具,带定位功能(输出调用处类型名、方法名、行,点击可追踪到)

这个博客介绍了一个名为XLog的错误日志打印工具,它用于Android应用程序,具备定位功能,能够详细记录调用堆栈信息,并提供异常处理和日志保存到文件的功能。XLog支持自定义日志标签,可以打印JSON格式的数据,并且可以在控制台和文件中输出日志。
摘要由CSDN通过智能技术生成

import android.content.Context;
import android.os.Environment;
import android.util.Log;

import com.hjq.toast.ToastUtils;
import com.mlibs.library.common.utils.IOUtils;
import com.mlibs.library.common.utils.StringUtil;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 错误日志打印工具,带定位功能(输出调用处类型名、方法名、行,点击可追踪到)
 */

public class XLog {
    /** 是否打印日志 */
    public static boolean isConsoleLog = true;

    public static final String TEST_INFO = "";
    private static int stepNumber = 0;
    public static String TAG = "调试信息";
    private static int logsegmentSize = 3072;//最长为4*1024设置为

    /**
     * 打印错误信息
     *
     * @param msg 错误信息
     */
    public static void tipInfo(String msg) {
        if (isConsoleLog && BuildConfig.DEBUG) {
            ToastUtils.show(StringUtil.defaultIfBlank(msg, "null"));
        }
    }

    /**
     * 打印错误信息
     *
     * @param msg 错误信息
     */
    public static void tipDialog(Context context, String msg) {
        if (isConsoleLog && BuildConfig.DEBUG) {
            DialogUtil.showSimpleDialog(context, msg);
        }
    }

    /**
     * 普通日志输出
     *
     * @param localTag tag
     * @param logMsg   info
     */
    public static void commonLog(String localTag, String logMsg) {
        if (isConsoleLog) {
            if (logMsg.length() > logsegmentSize) {
                int count = logMsg.length() / logsegmentSize;
                for (int i = 0; i < count; i++) {
                    if (logMsg.length() > logsegmentSize) {
                        Log.v(localTag, logMsg.substring(0, logsegmentSize));
                        logMsg = logMsg.substring(logsegmentSize);
                    }
                }
            }
            Log.v(localTag, logMsg);
        }
    }

    private static String isEmpty(Object msg) {
        if (msg == null) {
            return "日志调用处为null";
        } else if (strNull.equals(msg)) {
            return "日志调用处为字符串null";
        } else if ("".equals(msg)) {
            return "日志调用处为空字符串\"\"";
        }
        return msg.toString();
    }

    /**
     * 显示异常信息
     *
     * @param e 异常信息
     */
    public static String getExceptionInfo(Throwable e) {
        return Log.getStackTraceString(e);
    }

    /**
     * 显示异常信息
     *
     * @param e 异常信息
     */
    public static void printExceptionInfo(Throwable e) {
        if (isConsoleLog) {
            Log.e(TAG, "抛异常了" + Log.getStackTraceString(e));
//            printMsgToFile(getStackTrace(), "输出异常日志", Log.getStackTraceString(e));
        }
    }

    /**
     * 提示信息
     *
     * @param msg 错误信息
     */
    public static void file(String msg) {
        if (!isConsoleLog) return;
        file("调试信息", msg);
    }

    /**
     * 打印错误信息
     *
     * @param msg 错误信息
     */
    public static void file(String fileName, String msg) {
        if (!isConsoleLog) return;
        String content = "-----------------" + DateUtil.formatCurrentDate(DateUtil.REGEX_DATE_TIME) + "-------------------\n\n" + msg + "\n\n\n";
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
//            String appCrashPath = Environment.getExternalStorageDirectory().getPath() + File.separator + "crash" + File.separator;
            String appCrashPath = Constant.APP_CRASH_PATH;
            if (new File(appCrashPath).mkdirs()) {
                Log.e(TAG, "创建日志文件夹失败!!!");
                return;
            }
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(appCrashPath + fileName + ".log", true);
                fos.write(content.getBytes());
            } catch (Exception e) {
                printExceptionInfo(e);
            } finally {
                IOUtils.close(fos);
            }
        }
    }

    /**
     * 打印步骤
     */
    public static void showStepLogInfo() {
        if (!isConsoleLog) return;
        showLogs("", "步骤" + stepNumber++);
    }

    /**
     * 打印错误信息
     */
    public static void showArgsInfo(Object... args) {
        if (!isConsoleLog) return;
        showLogs("", Arrays.toString(args));
    }

    /**
     * 调用处子类方法所在位置
     *
     * @param msg smg
     */
    public static void getChildLog(String msg) {
        if (!isConsoleLog) {
            return;
        }
        StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[4];
        String stackTraceMsgArr = stackTraceElement.toString();
        Log.i(TAG, stackTraceMsgArr.substring(stackTraceMsgArr.indexOf("(")) + "#" + stackTraceElement.getMethodName() + " msg:" + msg);
    }

    /**
     * 获取StackTraceElement对象-----当前调用XLog.showLogInfo()处的类信息(类名、方法名、行等)
     * 堆栈跟踪元素:当前调用Log.showLogInfo()处的类信息(类名、方法名、行等)
     *
     * @return .
     */
    private static String getStackTraceStr() {
        /*简化版:Thread.currentThread().getStackTrace()[4].toString().substring(23).replaceFirst("\\.", "#")*/
        StackTraceElement trace = Thread.currentThread().getStackTrace()[5];
        return "(" + trace.getFileName() + ":" + trace.getLineNumber() + ")" + "#" + trace.getMethodName() + "  ";
    }

    /**
     * 打印日志
     *
     * @param msg .
     */
    private static void showLogs(String tag, String msg) {
        msg = msg.replace("(", "(").replace(")", ")");
        if (msg.length() > logsegmentSize) {
            while (msg.length() > logsegmentSize) {
                Log.i(TAG, getStackTraceStr() + tag + msg);
                msg = msg.substring(logsegmentSize);
            }
        }
        Log.i(TAG, getStackTraceStr() + tag + msg);
    }

    private static String joPrefix = "{";
    private static String joSuffix = "}";
    private static String strNull = "null";

    public static void printJson(String headString, String jsonStr) {
        String tag = headString;
        String s = "@";
        if (headString.contains(s)) {
            tag = headString.substring(0, headString.indexOf(s));
            headString = headString.substring(headString.indexOf(s) + 1);
        }
        if (isConsoleLog) {
            if (jsonStr == null) {
                showLogs("", "调用处为null");
            } else {
                if (strNull.equals(jsonStr)) {
                    showLogs("", "调用处为null字符串");
                } else {
                    String message;
                    try {

                        if (jsonStr.startsWith(joPrefix)) {
                            JSONObject jsonObject = new JSONObject(jsonStr);
                            //最重要的方法,就一行,返回格式化的json字符串,其中的数字4是缩进字符数
                            message = jsonObject.toString(4);
                        } else {
                            if (jsonStr.startsWith("[")) {
                                JSONArray jsonArray = new JSONArray(jsonStr);
                                message = jsonArray.toString(4);
                            } else {
                                message = jsonStr;
                            }
                        }
                    } catch (JSONException e) {
                        message = jsonStr;
                    }

                    printLine(tag, true);
                    message = headString + System.getProperty("line.separator") + message;
                    String[] lines = message.split(System.getProperty("line.separator"));
                    for (String line : lines) {
                        if (line.length() <= logsegmentSize) {
                            Log.d(tag, "║ " + line);
                        } else {
                            while (line.length() > logsegmentSize) {
                                Log.d(tag, "║ " + line);
                                String msgs = line.substring(0, logsegmentSize);
                                line = line.replace(msgs, "");
                            }
                            Log.d(tag, "║ " + line);
                        }
                    }
                    printLine(tag, false);
                }
            }
        }
    }

    private static void printLine(String tag, boolean isTop) {
        if (isTop) {
            Log.d(tag, "╔═══════════════════════════════════════════════════════════════════════════════════════");
        } else {
            Log.d(tag, "╚═══════════════════════════════════════════════════════════════════════════════════════");
        }
    }

}

 

超级 Toast博客地址:悬浮窗需求终结者已投入公司项目多时,没有任何毛病,可胜任任何需求,点击下载Demo想了解实现原理的可以点击此链接查看:XToast 源码本框架意在解决一些极端需求,如果是普通的 Toast 封装推荐使用 ToastUtils集成步骤dependencies {     implementation 'com.hjq:xtoast:2.0' }使用案例new XToast(XToastActivity.this) // 传入 Application 表示设置成全局的         .setView(R.layout.toast_hint)         .setDraggable() // 设置成可拖拽的 .setDuration(1000) // 设置显示时长 .setAnimStyle(android.R.style.Animation_Translucent) // 设置动画样式         .setImageDrawable(android.R.id.icon, R.mipmap.ic_dialog_tip_finish)         .setText(android.R.id.message, "点我消失")         .setOnClickListener(android.R.id.message, new OnClickListener<TextView>() {             @Override             public void onClick(XToast toast, TextView view) { // 点击这个 View 后消失                 toast.cancel();             }         })         .show();混淆规则-keep class com.hjq.xtoast.** {*;}框架亮点(原生 Toast 无法实现的功能)支持自定义 Toast 动画样式支持自定义 Toast 显示时长支持监听 Toast 的显示和销毁支持监听 Toast点击事件支持一键开启 Toast 拖拽功能支持 Toast 全局显示(需要权限)作者的其他开源项目架构工程:AndroidProject权限封装:XXPermissions吐司封装:ToastUtils标题栏封装:TitleBarAndroid技术讨论Q群:78797078
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值