您的位置:首页 > 移动开发 > Android开发

Android log的常见问题和常用方法

2016-12-23 17:50 411 查看
最近在总结了以下log的常见问题和常用方法,由于网络上的log框架太多,看了几个热门的也选择不了自己喜欢的,那就从中分析实用代码,从而实用到自己的工程中。



如何自动获取tag-即类名

如何打印线程和调用位置

如何打印异常

如何打印JSON

如何打印xml

如何打印对象 包含集合及数组

如何打印长数据

其他

如何自动获取tag-即类名

public class LogTest {
public String getTag() {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
int traceOffset = getStackOffset(trace);
String tagClassName = trace[traceOffset].getClassName();
return getSimpleClassName(tagClassName);
}

private int getStackOffset(StackTraceElement[] trace) {
int traceOffset = 3; // 0为VMStack,1为Thread,2为本类,固至少从3开始
for (int i = traceOffset; i < trace.length; i++) {
StackTraceElement e = trace[i];
String name = e.getClassName();
if (name.equals(LogTest.class.getName())) {
// 打到自己类,得知调用本方法的类栈,从而得知要输出的tag的类
traceOffset = i;
break;
}
}
return traceOffset;
}

private String getSimpleClassName(String name) {
int lastIndex = name.lastIndexOf(".");
return name.substring(lastIndex + 1).split("\\$")[0];
}
}


Log.i("cyy", LogTest.getTag());  // 执行
I/cyy: SplashActivity// 输出,SplashActivity就是执行上一行代码的类


如何打印线程和调用位置

public class LogTest {

public String getThreadInfo(){
return Thread.currentThread().getName(); // 获取当前线程名
}

public String showMethod(int methodCount){
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
int traceOffset = getStackOffset(trace);
StringBuilder builder = new StringBuilder();

// 获取当前有效栈,并倒序输出执行行的信息
for (int i = methodCount; i > 0; i--) {
int stackIndex = i + traceOffset - 1;
builder.append(getSimpleClassName(trace[stackIndex].getClassName())).append(".")
.append(trace[stackIndex].getMethodName()).append(" ").append(" (")
.append(trace[stackIndex].getFileName()).append(":").append(trace[stackIndex].getLineNumber())
.append(")");
builder .append("\n");
}
return  builder.toString();
}

private int getStackOffset(StackTraceElement[] trace) {
int traceOffset = 3; // 0为VMStack,1为Thread,2为本类,固至少从3开始
for (int i = traceOffset; i < trace.length; i++) {
StackTraceElement e = trace[i];
String name = e.getClassName();
if (name.equals(LogTest.class.getName())) {
// 打到自己类,得知调用本方法的类栈,从而得知要输出的tag的类
traceOffset = i;
break;
}
}
return traceOffset;
}

private String getSimpleClassName(String name) {
int lastIndex = name.lastIndexOf(".");
return name.substring(lastIndex + 1).split("\\$")[0];
}

}


执行代码和结果:



如何打印异常

来自系统自带的Log类静态方法getStackTraceString。

public static String getStackTraceString(Throwable tr) {
if (tr == null) {
return "";
}

Throwable t = tr;
while (t != null) {
if (t instanceof UnknownHostException) {
return "";
}
t = t.getCause();
}

StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
tr.printStackTrace(pw);
pw.flush();
return sw.toString();
}


如何打印JSON

public String json(String json) {
int JSON_INDENT = 2; // 格式
if (TextUtils.isEmpty(json)) {
return "Empty - json";
}
try {
json = json.trim();
if (json.startsWith("{")) {
JSONObject jsonObject = new JSONObject(json);
return jsonObject.toString(JSON_INDENT);
}
if (json.startsWith("[")) {
JSONArray jsonArray = new JSONArray(json);
return jsonArray.toString(JSON_INDENT);
}
return "Invalid Json";
} catch (JSONException e) {
return Log.getStackTraceString(e);
}
}


如何打印xml

public String xml(String xml) {

if (TextUtils.isEmpty(xml)) {
return "Empty - xml";
}
try {
Source xmlInput = new StreamSource(new StringReader(xml));
StreamResult xmlOutput = new StreamResult(new StringWriter());
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(xmlInput, xmlOutput);
return xmlOutput.getWriter().toString().replaceFirst(">", ">\n");
} catch (TransformerException e) {
return Log.getStackTraceString(e);
}
}


如何打印对象 (包含集合及数组)

如何依赖其他库,如gson打印对象就容易多了:

public static String toJson(Object cls) {
if (null == cls) {
return "";
}
String obj = new Gson().toJson(cls);
return obj;
}


如果没有就通过反射的方式(支付打印集合,数组,Bundle)

先看效果:



import android.content.Intent;
import android.os.Bundle;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class LogTest {
public final String BR = System.getProperty("line.separator");

public String objectToString(Object object) {
return objectToString(object, 0);
}

public String objectToString(Object object, int childLevel) {
if (object == null) {
return "Object[object is null]";
}
if (childLevel > 2) {
return object.toString();
}
if (Map.class.isAssignableFrom(object.getClass())) {
return parseMap((Map) object);
} else if (Bundle.class.isAssignableFrom(object.getClass())) {
return parseBundle((Bundle) object);
} else if (Collection.class.isAssignableFrom(object.getClass())) {
return parseCollection((Collection) object);
} else if (object.getClass().isArray()) { // 数组
return parseArray(object);
}

if (object.toString().startsWith(object.getClass().getName() + "@")) {
StringBuilder builder = new StringBuilder();
getClassFields(object.getClass(), builder, object, false, childLevel);
Class superClass = object.getClass().getSuperclass();
int i = 0;
while (!superClass.equals(Object.class)) {
i++;
getClassFields(superClass, builder, object, true, childLevel);
superClass = superClass.getSuperclass();
if (i > 5) break;
}
return builder.toString();
}
return object.toString();
}

private void getClassFields(Class cla, StringBuilder builder, Object o, boolean isSubClass, int childOffset) {
if (cla.equals(Object.class)) {
return;
}
if (isSubClass) {
builder.append(BR + BR + "=> ");
}
String breakLine = "";
builder.append(cla.getSimpleName() + " {");
Field[] fields = cla.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
if ((!cla.isMemberClass()) || (isStaticInnerClass(cla)) || (i != 0)) {
Object subObject = null;
try {
subObject = field.get(o);
} catch (IllegalAccessException e) {
subObject = e;
} finally {
if (subObject != null) {
if ((subObject instanceof String)) {
subObject = "\"" + subObject + "\"";
} else if ((subObject instanceof Character)) {
subObject = "'" + subObject + "'";
}
if (childOffset < 2) {
subObject = objectToString(subObject, childOffset + 1);
}
}
String formatString = breakLine + "%s = %s, ";
builder.append(String.format(formatString, new Object[]{field.getName(), subObject == null ? "null" : subObject
.toString()}));
}
}
}
if (builder.toString().endsWith("{")) {
builder.append("}");
} else {
builder.replace(builder.length() - 2, builder.length() - 1, breakLine + "}");
}
}

private boolean isStaticInnerClass(Class cla) {
if ((cla != null) && (cla.isMemberClass())) {
int modifiers = cla.getModifiers();
if ((modifiers & 0x8) == 8) {
return true;
}
}
return false;
}

private String parseMap(Map map) {
String msg = map.getClass().getName() + " [" + BR;
Set<Object> keys = map.keySet();
for (Object key : keys) {
String itemString = "%s -> %s" + BR;
Object value = map.get(key);
if (value != null) {
if ((value instanceof String)) {
value = "\"" + value + "\"";
} else if ((value instanceof Character)) {
value = "'" + value + "'";
}
}
msg = msg + String.format(itemString, new Object[]{objectToString(key),
objectToString(value)});
}
return msg + "]";
}

private String parseCollection(Collection collection) {
if (collection == null) {
return "";
}
String simpleName = collection.getClass().getName();
String msg = "%s size = %d [" + BR;
msg = String.format(msg, new Object[]{simpleName, Integer.valueOf(collection.size())});
if (!collection.isEmpty()) {
Iterator<Object> iterator = collection.iterator();
int flag = 0;
while (iterator.hasNext()) {
String itemString = "[%d]:%s%s";
Object item = iterator.next();
msg = msg + String.format(itemString, new Object[]{Integer.valueOf(flag), objectToString(item), flag++ < collection
.size() - 1 ? "," + BR : BR});
}
}
return msg + "]";
}

private String parseBundle(Bundle bundle) {
if (bundle == null) {
return "";
}
StringBuilder builder = new StringBuilder(bundle.getClass().getName() + " [" + BR);
for (String key : bundle.keySet()) {
builder.append(String.format("'%s' => %s " + BR, new Object[]{key,
objectToString(bundle.get(key))}));
}
builder.append("]");
return builder.toString();
}

private String parseArray(Object array) {
StringBuilder result = new StringBuilder();
traverseArray(result, array);
return result.toString();
}

public int getArrayDimension(Object object) {
int dim = 0;
for (int i = 0; i < object.toString().length(); i++) {
if (object.toString().charAt(i) != '[') {
break;
}
dim++;
}
return dim;
}

public char getType(Object object) {
String str = object.toString();
return str.substring(str.lastIndexOf("[") + 1, str.lastIndexOf("[") + 2).charAt(0);
}

private void traverseArray(StringBuilder result, Object array) {
if (getArrayDimension(array) == 1) {
switch (getType(array)) {
case 'I':
result.append(Arrays.toString((int[]) array));
break;
case 'D':
result.append(Arrays.toString((double[]) array));
break;
case 'Z':
result.append(Arrays.toString((boolean[]) array));
break;
case 'B':
result.append(Arrays.toString((byte[]) array));
break;
case 'S':
result.append(Arrays.toString((short[]) array));
break;
case 'J':
result.append(Arrays.toString((long[]) array));
break;
case 'F':
result.append(Arrays.toString((float[]) array));
break;
case 'L':
Object[] objects = (Object[]) array;
result.append("[");
for (int i = 0; i < objects.length; i++) {
result.append(objectToString(objects[i]));
if (i != objects.length - 1) {
result.append(",");
}
}
result.append("]");
break;
case 'C':
case 'E':
case 'G':
case 'H':
case 'K':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
default:
result.append(Arrays.toString((Object[]) array));
}
} else {
result.append("[");
for (int i = 0; i < ((Object[]) array).length; i++) {
traverseArray(result, ((Object[]) (Object[]) array)[i]);
if (i != ((Object[]) array).length - 1) {
result.append(",");
}
}
result.append("]");
}
}
}


如何打印长数据

1,循环:

public void i(String tag, String msg) {
if (msg.length() <= 1000) {
Log.i(tag, msg);
} else {
int maxLogSize = 1000;
for (int i = 0; i <= msg.length() / maxLogSize; i++) {
int start = i * maxLogSize;
int end = (i + 1) * maxLogSize;
end = end > msg.length() ? msg.length() : end;
i(tag, msg.substring(start, end));
}
}
}


2.换行就输出:

public void logContent(String tag, String msg) {
String[] lines = msg.split(System.getProperty("line.separator"));// 换行符
for (String line : lines) {
Log.i(tag, msg);
}
}


其他

如何保存日记,下篇文章介绍
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息