Android的日志默认是带TAG的这种形式,如Log.i(String TAG, String msg),在每个类中都要定义TAG,比较烦,现利用java调用栈获取调用处所在类名,自动将类名作为TAG,避免了每个类写TAG,将重心放到msg上。
具体代码如下:
public class LogUtils {
private static StackTraceElement[] currentThread;
private static String tagName;
private static String msgT;
private static String msgC;
private static String callTraceStack;
private static int curLogLevel = Log.VERBOSE;
public static int getCurLogLevel() {
return curLogLevel;
}
public static void setCurLogLevel(int curLogLevel) {
LogUtils.curLogLevel = curLogLevel;
}
public synchronized static void initTrace(String msg, int... isPrintStack) {
int isPrintStackOne = isPrintStack.length > 0 ? isPrintStack[0] : 10;
currentThread = Thread.currentThread().getStackTrace();
// vm调用栈中此方法所在index:2:VMStack.java:-2:getThreadStackTrace()<--Thread.java:737:getStackTrace()<--
int curentIndex = 4;
String className = currentThread[curentIndex].getFileName();
int endIndex = className.lastIndexOf(".");
tagName = endIndex < 0 ? className : className.substring(0, endIndex);
msgT = "[" + className + ":" + currentThread[curentIndex].getLineNumber() + ":"
+ currentThread[curentIndex].getMethodName() + "()]---";
msgC = "msg:[" + msg + "]";
if (isPrintStackOne > 0) {
StringBuilder sb = new StringBuilder();
sb.append("callTraceStack:[");
for (int i = curentIndex; i < curentIndex + isPrintStackOne && i < currentThread.length; i++) {
sb.append(currentThread[i].getFileName() + ":" + currentThread[i].getLineNumber() + ":"
+ currentThread[i].getMethodName() + "()" + "<--");
}
sb.append("]");
callTraceStack = sb.toString();
msgC += callTraceStack;
}
}
public static void e(String msg, boolean printStack) {
e(msg, printStack ? 105 : 0);
}
public static void w(String msg, boolean printStackNum) {
w(msg, printStackNum ? 105 : 0);
}
public static void d(String msg, boolean printStackNum) {
d(msg, printStackNum ? 105 : 0);
}
public static void v(String msg, boolean printStackNum) {
v(msg, printStackNum ? 105 : 0);
}
public static void i(String msg, boolean printStackNum) {
i(msg, printStackNum ? 105 : 0);
}
public static void e(String msg, int... printStackNum) {
if (curLogLevel > Log.ERROR) {
return;
}
initTrace(msg, printStackNum.length > 0 ? printStackNum[0] : 0);
Log.e(tagName, msgT + msgC);
}
public static void w(String msg, int... printStackNum) {
if (curLogLevel > Log.WARN) {
return;
}
initTrace(msg, printStackNum.length > 0 ? printStackNum[0] : 0);
Log.w(tagName, msgT + msgC);
}
public static void d(String msg, int... printStackNum) {
if (curLogLevel > Log.DEBUG) {
return;
}
initTrace(msg, printStackNum.length > 0 ? printStackNum[0] : 0);
Log.d(tagName, msgT + msgC);
}
public static void v(String msg, int... printStackNum) {
if (curLogLevel > Log.VERBOSE) {
return;
}
initTrace(msg, printStackNum.length > 0 ? printStackNum[0] : 0);
Log.v(tagName, msgT + msgC);
}
public static void i(String msg, int... printStackNum) {
if (curLogLevel > Log.INFO) {
return;
}
initTrace(msg, printStackNum.length > 0 ? printStackNum[0] : 0);
Log.i(tagName, msgT + msgC);
}
}
说明:
1. 使用方式:LogUtil.v("~test~");
2. public static void v(String msg, int... printStackNum)中printStackNum为可选参数,表示打印多少层调用栈
3. curLogLevel表示当前打印日志的最低等级,比如设置为Log.INFO,则info以上的打印,以下的不打印,这样在Debug阶段,设置为
Log.VERBOSE,在Release阶段设置为Log.ERROR或者Log.ASSERT,就可以不打印哪些调试日志
4. 这样使用Thread.currentThread().getStackTrace(),效率可能比较低,调试可以用,发行版本,最好关闭日志如果有大神有优化方案,不吝指点一二。