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
- Android log的常见问题和常用方法
- android.util.Log常用的方法
- android.util.Log常用的方法
- Android Log命令常用方法
- Android log常用分析方法
- Android日志工具类Log方法的级别和使用方法
- android NDK和源码中输出Log信息的方法
- Android adb常用指令和常见问题
- Android打Log的方法
- 通过logcat 过滤 Log 的常用方法
- String的常用方法及常见问题
- 常用Log抓取方法
- 常用抓log方法
- 17 常用的Sql技巧和常见问题
- 常用的SQL技巧和常见问题
- android handler和message的常用方法
- Android系统adb调试命令及常用抓log方法
- Android系统adb调试命令及常用抓log方法
- 欢迎使用CSDN-markdown编辑器
- 【MySQL】mysql中函数DISTINCT、group by、CONCAT、GROUP_CONCAT的使用以及mysql group_concat函数被截断的问题
- C#+OpenGL+FreeType显示3D文字(1) - 从TTF文件导出字形贴图
- oj题目回顾(1056)C语言习题5.22--输出已交换后的两个值
- IOS运行时实现自己的KVO
- Android log的常见问题和常用方法
- mongodb数据库在Linux上的使用
- Spring事务管理—aop:pointcut expression解析
- 使用nginx搭建https服务器
- LeetCode 1、Two Sum
- IOS 基础-define、const、extern、全局变量
- 理解 Thread.Sleep 函数
- 网页中实现六边形的N种姿势
- struts2的工作流程--解析