Is there any way to automatically log the method name in Android?
I'm using this kind of pattern:
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());
Where l is my wrapper round Androids Log.v which takes String... args. This gives logcat output like this:
FooProvider.update() Uri: foo bar etc
What I'm looking for is a way to log the method name, in this case update(), automatically 开发者_运维问答and in a way which survives refactoring the way TAG does. I've seen the class.getMethods() call but can't see a way to index the returned list with the current method at runtime.
You may want to wrap these statements in a constant, so they get compiled out for your published version (which won't be printing Log.v statements anyway), but you can do something like this:
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;
}
}
It will depend upon how you call it to determine which StackTraceElement
index you'll want, just debug it or play around a few times to find it.
When you compile your published version, just set FINAL_CONSTANT_IS_LOCAL to false and that code block will go away, always returning TAG.
It seems expensive but you could use
String Method = Thread.currentThread().getStackTrace()[2].getMethodName();
The reason you use an index of 2, is that 0 = would return currentThread and 1 = getStackTrace. This works on Java 1.5 and above, I would wrap it in some kind of if (DEBUG) {} thing so it's not in production code
Of course you will need to adjust the depth if you put that inside a method etc.
I created a MethodLogger class that I instantiate at the beginning of a method.
It figures out the class name & method name.
It also has a handy elapsedTime logger that you access by calling methodLogger.end().
Usage - put this at the beginning of a method to log:
MethodLogger methodLogger = new MethodLogger();
To optionally log some debug messages:
methodLogger.d("optionally log some debug messages");
To log when a method ends and show the elapsed time since the method started:
methodLogger.end();
Results:
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 class:
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));
}
}
}
I have a custom logger that wraps around android Log.
it will display class name, method name and line number.
http://www.hautelooktech.com/2011/08/15/android-logging/
you could make static methods like these and call them from the beginning and end of the methods you want to debug:
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;
}
And
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;
}
I created this Logging utility for Android with a few more features,other than entry-exit logs. You might find it useful.
You only need addition message and input to this function to auto create log
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();
}
精彩评论