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

来源:互联网 发布:pptv网络电视怎么看直播 编辑:程序博客网 时间:2024/05/19 23:11

最近在总结了以下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);        }    }

其他

如何保存日记,下篇文章介绍

1 0