Android可跳转指定位置的Log

在使用Android Studio开发的时候,当程序出现错误的时候,我们通常可以通过点击错误日志跳转到指定方法出错的那一行。例如,下图便是常见的空指针异常所抛出的错误日志:
这里写图片描述

然而,当我们自己使用Log.x去打印Log的时候却没有这种跳转的功能,只能显示打印的信息。那么如何实现让我们打印的日志也能跳转呢?其实方法很简单,只要让我们打印的日志信息符合系统的要求,你输出的日志信息就会自动实现可跳转的功能。所以只要让你的输出的日志符合这种要求便可。这里,我们可以使用JDK自带的StackTraceElement类来帮助我们实现这种要求,StackTraceElement可以简单理解为是记录调用栈信息的类,也就是说,我们的输出信息含有了这种调用栈信息,便可以实现自动跳转的功能。

下面给出两个种实现方法:

  public class LogUtils {

public static void PrintD(String content, Object... args) {
    for (int i = 0; i < Thread.currentThread().getStackTrace().length; i++) {
        String realContent = getContent(content, i, args);
        Log.d("default", realContent);
    }
}

public static void PrintD(String tag, String content, Object... args) {
        Log.d(tag, getContent(content, 4, args));
}

private static String getNameFromTrace(StackTraceElement[] traceElements, int place) {
    StringBuilder taskName = new StringBuilder();
    //判断调用栈的层级,大于place的才打印Log输出
    if (traceElements != null && traceElements.length > place) {
        StackTraceElement traceElement = traceElements[place];
        taskName.append(traceElement.getMethodName());
        taskName.append("(").append(traceElement.getFileName()).append(":").append(traceElement.getLineNumber()).append(")");
    }
    return taskName.toString();
}

private static String getContent(String msg, int place, Object... args) {
    try {
        String sourceLinks = getNameFromTrace(Thread.currentThread().getStackTrace(), place);
        return sourceLinks + String.format(msg, args);
    } catch (Throwable throwable) {
        return msg;
    }
}
}

//在下面调用
  @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    printD("MyTag:", "xxxxx");

}



private StackTraceElement getTargetStackTraceElement() {
    // find the target invoked method
    StackTraceElement targetStackTrace = null;
    boolean shouldTrace = false;
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    for (StackTraceElement stackTraceElement : stackTrace) {
    //通过判断是否属于该类,来进行过滤掉无用的信息
        boolean isLogMethod = stackTraceElement.getClassName().equals(L.class.getName());
        if (shouldTrace && !isLogMethod) {
            targetStackTrace = stackTraceElement;
            break;
        }
        shouldTrace = isLogMethod;
    }
    return targetStackTrace;
}

public static void e(String tag, String msg, Object... params) {
    if (!sDebug) return;

    String finalTag = getFinalTag(tag);
    StackTraceElement targetStackTraceElement = getTargetStackTraceElement();
    Log.e(finalTag, "(" + targetStackTraceElement.getFileName() + ":"
            + targetStackTraceElement.getLineNumber() + ")");
    Log.e(finalTag, String.format(msg, params));
}

//在下面调用
public class L{
    private static boolean sDebug = true;
    private static String sTag = "zhy";

    public static void init(boolean debug, String tag){
        L.sDebug = debug;
        L.sTag = tag;
    }

    public static void e(String msg, Object... params){
        e(null, msg, params);
    }

    public static void e(String tag, String msg, Object[] params){
        if (!sDebug) return;
        tag = getFinalTag(tag);
        //TODO 通过stackElement打印具体log执行的行数
        Log.e(tag, content);
    }

    private static String getFinalTag(String tag){
        if (!TextUtils.isEmpty(tag)){
            return tag;
        }
        return sTag;
    }
}

上面两种实现方法都是使用了 StackTraceElement类,主要区别在于:如何过滤掉无用信息。在下图中,是一些没有进行过滤的调用栈信息,而我们只需要蓝色部分字体所在行的信息。所以,怎样去掉其他行显得很重要,上面则是两种实现方法。
这里写图片描述

第一种方法中,使用 if (traceElements != null && traceElements.length > place) ,通过调用层级place进行判断,因为处于低层的信息肯定是系统打印的信息(如上图中的getThreadStackTrace(VMStack java-2)),这个肯定不是我们想看到的。所以,只要控制好层级数并可以过滤掉掉这些无用的信息。上文中代码选用的层级为4。具体根据自己的实现进行更改(即上面的LogUtils是怎样实现的 )。

第二种方法是,通过stackTraceElement.getClassName().equals(L.class.getName()),即打印的信息是否是Log方法的调用方打印出来的,如上面的L类。在L类中调用打印Log,所以我们也只关心L类中输出的信息,而不去关心其他基类的信息。于是,通过判断类名是否为L类也可过滤掉无用信息。

上述两种方法均可实现过滤的效果,可以根据自身喜好进行选择。

参考文章:

Android打印日志,实现快速定位源代码 ——大头呆

Android 从StackTraceElement反观Log库 —— 鸿洋_

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值