Last active
August 29, 2015 14:26
-
-
Save jmcd/5fa3d39e0eb2d9c67ebf to your computer and use it in GitHub Desktop.
Android Log Wrapper to: [1] automatically (and probably expensively) add class/method tracing to debug messages and [2] ability to hack in loggint to other places (e.g. a dirty log to a TextView)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Foo { | |
private void bar() { | |
L.dt("hello world!"); // Logs with tag "Foo" and message "bar hello world" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
final TextView tv = (TextView) this.findViewById(R.id.textView); | |
tv.setMovementMethod(new ScrollingMovementMethod()); | |
L.PRINTLNS.add(new L.Println() { | |
@Override | |
public int invoke(int priority, final String tag, final String msg) { | |
if (MainActivity.this.debugStartTime == -1) { | |
MainActivity.this.debugStartTime = System.currentTimeMillis(); | |
} | |
final long time = System.currentTimeMillis() - MainActivity.this.debugStartTime; | |
MainActivity.this.runOnUiThread(new Runnable() { | |
@Override | |
public void run() { | |
tv.append(String.format("[%d] %s.%s\n", time, tag, msg)); | |
} | |
}); | |
return 0; | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.util.Log; | |
import java.util.ArrayList; | |
import java.util.List; | |
public final class L { | |
public static final String MAGICAL_EXPENSIVE_AUTO_TAG = "JPgpKvpxrnB1zrs8WnGqVNTeK0NgMyY8SXnMEaXPnTY="; | |
public final static List<Println> PRINTLNS = new ArrayList<>(); | |
private final static String[] NAMES_OF_EXCLUDED_CLASSES = new String[]{L.class.getName()}; | |
private static ThreadLocal<StackTraceElement> callerStackTraceElement; | |
static { | |
PRINTLNS.add(new Println() { | |
@Override | |
public int invoke(int priority, String tag, String msg) { | |
return Log.println(priority, tag, msg); | |
} | |
}); | |
} | |
public static int v(String tag, String msg) { | |
return println(Log.VERBOSE, tag, msg); | |
} | |
public static int v(String tag, String msg, Throwable tr) { | |
return println(Log.VERBOSE, tag, msg + '\n' + Log.getStackTraceString(tr)); | |
} | |
public static int d(String tag, String msg) { | |
return println(Log.DEBUG, tag, msg); | |
} | |
public static int d(String tag, String msg, Throwable tr) { | |
return println(Log.DEBUG, tag, msg + '\n' + Log.getStackTraceString(tr)); | |
} | |
public static int i(String tag, String msg) { | |
return println(Log.INFO, tag, msg); | |
} | |
public static int i(String tag, String msg, Throwable tr) { | |
return println(Log.INFO, tag, msg + '\n' + Log.getStackTraceString(tr)); | |
} | |
public static int w(String tag, String msg) { | |
return println(Log.WARN, tag, msg); | |
} | |
public static int w(String tag, String msg, Throwable tr) { | |
return println(Log.WARN, tag, msg + '\n' + Log.getStackTraceString(tr)); | |
} | |
public static int w(String tag, Throwable tr) { | |
return println(Log.WARN, tag, Log.getStackTraceString(tr)); | |
} | |
public static int e(String tag, String msg) { | |
return println(Log.ERROR, tag, msg); | |
} | |
public static int e(String tag, String msg, Throwable tr) { | |
return println(Log.ERROR, tag, msg + '\n' + Log.getStackTraceString(tr)); | |
} | |
public static int dt() { | |
return dt(null); | |
} | |
public static int dt(String msg) { | |
SetCaller(); | |
try { | |
String s = callerStackTraceElement.get().getMethodName(); | |
if (msg != null) { | |
s += " " + msg; | |
} | |
return d(MAGICAL_EXPENSIVE_AUTO_TAG, s); | |
} finally { | |
UnsetCaller(); | |
} | |
} | |
private static void SetCaller() { | |
final StackTraceElement ste = CallerClassTool.getCallerStackTraceElement(NAMES_OF_EXCLUDED_CLASSES); | |
callerStackTraceElement = new ThreadLocal<>(); | |
callerStackTraceElement.set(ste); | |
} | |
private static void UnsetCaller() { | |
callerStackTraceElement.remove(); | |
callerStackTraceElement = null; | |
} | |
private static String SimpleClassName() { | |
String className = callerStackTraceElement.get().getClassName(); | |
int i = className.lastIndexOf('.'); | |
if (i != -1) { | |
className = className.substring(i + 1); | |
} | |
return className; | |
} | |
public static int println(int priority, String tag, String msg) { | |
if (tag.equals(MAGICAL_EXPENSIVE_AUTO_TAG)) { | |
tag = SimpleClassName(); | |
} | |
int numberOfBytesWritten = 0; | |
for (Println pln : PRINTLNS) { | |
numberOfBytesWritten += pln.invoke(priority, tag, msg); | |
} | |
return numberOfBytesWritten; | |
} | |
public interface Println { | |
int invoke(int priority, String tag, String msg); | |
} | |
} | |
public class CallerClassTool { | |
public static StackTraceElement getCallerStackTraceElement(String[] namesOfExcludedClasses) { | |
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); | |
String callerClassName = null; | |
for (int i = 1; i < stackTrace.length; i++) { | |
StackTraceElement ste = stackTrace[i]; | |
String className = ste.getClassName(); | |
if (className.indexOf("java.lang.Thread") == 0) { | |
continue; | |
} | |
if (className.equals(CallerClassTool.class.getName())) { | |
continue; | |
} | |
for (String excl : namesOfExcludedClasses) { | |
if (className.equals(excl)) { | |
continue; | |
} | |
} | |
if (callerClassName == null) { | |
callerClassName = className; | |
} else if (!callerClassName.equals(className)) { | |
return ste; | |
} | |
} | |
return null; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment