有没有办法在Android中自动记录方法名称?

时间:2011-07-31 18:14:55

标签: android logging logcat

我正在使用这种模式:

public class FooProvider extends ContentProvider {
    private static final String TAG = FooProvider.class.getSimpleName(); 
    ...

    @Override
    public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
        l.v(TAG, TAG + ".update() Uri:" + uri.toString() + " " + db.getPath());

其中l是我的包装器圆形Androids Log.v,它采用String ... args。这给出了这样的logcat输出:

FooProvider.update() Uri: foo bar etc

我正在寻找的是一种记录方法名称的方法,在这种情况下是update(),自动地以一种方式记录TAG的重构方式。我已经看过class.getMethods()调用但看不到在运行时用当前方法索引返回列表的方法。

7 个答案:

答案 0 :(得分:15)

您可能希望将这些语句包装在一个常量中,因此它们会针对您发布的版本编译出来(无论如何都不会打印Log.v语句),但您可以这样做:

private static final boolean FINAL_CONSTANT_IS_LOCAL = true;
private static final String TAG = FooProvider.class.getSimpleName();

private String getLogTagWithMethod() {
    if (FINAL_CONSTANT_IS_LOCAL) {
        Throwable stack = new Throwable().fillInStackTrace();
        StackTraceElement[] trace = stack.getStackTrace();
        return trace[0].getClassName() + "." + trace[0].getMethodName() + ":" + trace[0].getLineNumber();
    } else {
        return TAG;
    }
}

这取决于你如何调用它来确定你想要的StackTraceElement索引,只需调试它或玩几次就可以找到它。

编译已发布的版本时,只需将FINAL_CONSTANT_IS_LOCAL设置为false,该代码块将消失,并始终返回TAG。

答案 1 :(得分:9)

看起来很贵,但你可以使用

String Method = Thread.currentThread().getStackTrace()[2].getMethodName();

使用索引2的原因是0 =将返回currentThread,1 = getStackTrace。这适用于Java 1.5及更高版本,我会将它包装在某种if(DEBUG){}中,所以它不在生产代码中

当然,如果你把它放在方法等中,你需要调整深度。

答案 2 :(得分:3)

我创建了一个 MethodLogger类,我在方法的开头实例化。
它计算了班级名称和方法名称 它还有一个方便的 elapsedTime logger ,您可以通过调用 methodLogger.end()来访问它。

用法 - 将其放在记录方法的开头:

MethodLogger methodLogger = new MethodLogger();

可选择记录一些调试消息:

methodLogger.d("optionally log some debug messages");

要记录方法何时结束并显示自方法开始以来经过的时间:

methodLogger.end();

结果:

D/com.domain.app.MainActivity: onCreate()
D/com.domain.app.MainActivity: onCreate() optionally log some debug messages
D/com.domain.app.MainActivity: onCreate() finished in 0.123 seconds.

MethodLogger类:

public class MethodLogger {

    // Private Fields
    private String tag;
    private String methodName;
    private long startTime;


    // Constructor
    public MethodLogger() {
        if (BuildConfig.DEBUG) { // Avoid doing any processing nor debug logging when built for RELEASE.
            StackTraceElement callersStackTraceElement = Thread.currentThread().getStackTrace()[3];
            tag = callersStackTraceElement.getClassName();
            methodName = callersStackTraceElement.getMethodName() + "()";
            startTime = System.currentTimeMillis();
            Log.d(tag, this.methodName);
        }
    }


    // Public Methods
    public void e(String message) {
        Log.e(tag, methodName + " " + message);
    }

    public void i(String message) {
        Log.i(tag, methodName + " " + message);
    }

    public void d(String message) {
        if (BuildConfig.DEBUG) { // Avoid doing any debug logging when built for RELEASE.
            Log.d(tag, methodName + " " + message);
        }
    }

    public void end() {
        if (BuildConfig.DEBUG) { // Avoid doing any processing nor debug logging when built for RELEASE.
            long elapsedMillis = System.currentTimeMillis() - startTime;
            Log.d(tag, String.format("%s finished in %.3f seconds.", methodName, 0.001f * elapsedMillis));
        }
    }

}

答案 3 :(得分:2)

我有一个包装android Log的自定义记录器。

它将显示班级名称,方法名称和行号。

http://www.hautelooktech.com/2011/08/15/android-logging/

答案 4 :(得分:0)

您可以创建这样的静态方法,并从要调试的方法的开头和结尾调用它们:

    public static void entry_log(String id) {
                Throwable stack = new Throwable().fillInStackTrace();
                StackTraceElement[] trace = stack.getStackTrace();

                    Log.v("ENTRY",
                            id + " - " + trace[1].getClassName() + "."
                                    + trace[1].getMethodName() + ":"
                                    + trace[1].getLineNumber());
                    break;

            }

public void exit_log(String id) {
            Throwable stack = new Throwable().fillInStackTrace();
            StackTraceElement[] trace = stack.getStackTrace();

                Log.v("EXIT",
                        id + " - " + trace[1].getClassName() + "."
                                + trace[1].getMethodName() + ":"
                                + trace[1].getLineNumber());
                break;

        }

我为Android创建了this Logging utility,除了进入退出日志之外还有一些其他功能。您可能会发现它很有用。

答案 5 :(得分:0)

您可以查看Jake Wharton的timber library的Java代码。

确实,

中的主要观点
StackTraceElement[] stackTrace = new Throwable().getStackTrace();

这会返回一个StackTraceElement

数组

算法看起来像

  1. 创建一个新的Throwable实例并获取堆栈跟踪。
  2. 选择正确的StackTraceElement
  3. 清理它。
  4. 请在此处阅读更多内容 - https://medium.com/@wdziemia/timber-c733b1faa5b6

答案 6 :(得分:0)

您只需要添加消息并输入此功能即可自动创建日志

private static String buildMsg(String msg) {
    StringBuilder buffer = new StringBuilder();

    if (DETAIL_ENABLE) {
        final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[4];
        buffer.append("[ ");
        buffer.append(Thread.currentThread().getName());
        buffer.append(": ");
        buffer.append(stackTraceElement.getFileName());
        buffer.append(": ");
        buffer.append(stackTraceElement.getLineNumber());
        buffer.append(": ");
        buffer.append(stackTraceElement.getMethodName());
    }

    buffer.append("() ] _____ ");

    buffer.append(msg);

    return buffer.toString();
}