Android KLog源码分析
来源:互联网 发布:手机扫描ip软件 编辑:程序博客网 时间:2024/06/07 19:41
Android KLog源码分析
- Android KLog源码分析
- 代码结构
- 具体分析
- BaseLog
- FileLog
- JsonLog
- XmlLog
- 核心文件KLogjava分析
- 遇到的问题
- Android KLog源码分析
一直使用这个库,但没有仔细研究,今天就来研究一下,该库的地址:
KLog,在这里先感谢下作者,棒棒哒!
代码结构
整个代码的结构很简单,如下:
library klog BaseLog.java FileLog.java JsonLog.java XmlLog.java KLog.java KLogUtil.java
共六个文件:
- BaseLog.java,支持基本的log打印
- FileLog.java,支持以文件的形式保存log
- JsonLog.java,支持打印json对象和json数组
- XmlLog.java,支持打印Xml形式的log
具体分析
BaseLog
两个方法:
public class BaseLog { private static final int MAX_LENGTH = 4000; public static void printDefault(int type, String tag, String msg) { int index = 0; int length = msg.length(); int countOfSub = length / MAX_LENGTH; if (countOfSub > 0) {// 超过指定长度,粉刺打印,这样就避免了系统默认的log长度限制了 for (int i = 0; i < countOfSub; i++) { String sub = msg.substring(index, index + MAX_LENGTH); printSub(type, tag, sub); index += MAX_LENGTH; } printSub(type, tag, msg.substring(index, length));// 打印余数部分 } else { printSub(type, tag, msg); } } private static void printSub(int type, String tag, String sub) { switch (type) { case KLog.V: Log.v(tag, sub); break; case KLog.D: Log.d(tag, sub); break; case KLog.I: Log.i(tag, sub); break; case KLog.W: Log.w(tag, sub); break; case KLog.E: Log.e(tag, sub); break; case KLog.A: Log.wtf(tag, sub); break; } }}
这里突破了android系统的log字数限制,其实就是超过字数限制后,采用分次打印的方法来打印,其他代码不做分析,比较简单。
FileLog
三个方法
public class FileLog { private static final String FILE_PREFIX = "KLog_"; private static final String FILE_FORMAT = ".log"; /** * @param tag log tag * @param targetDirectory log file save dir * @param fileName log file name * @param headString log file 文件头 * @param msg log file log内容主体 */ public static void printFile(String tag, File targetDirectory, @Nullable String fileName, String headString, String msg) { fileName = (fileName == null) ? getFileName() : fileName; if (save(targetDirectory, fileName, msg)) { Log.d(tag, headString + " save log success ! location is >>>" + targetDirectory.getAbsolutePath() + "/" + fileName); } else { Log.e(tag, headString + "save log fails !"); } } /** * @param dic log file save dir * @param fileName og file name * @param msg log file log内容主体 * @return true if save success */ private static boolean save(File dic, @NonNull String fileName, String msg) { File file = new File(dic, fileName); try { OutputStream outputStream = new FileOutputStream(file); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "UTF-8"); outputStreamWriter.write(msg); outputStreamWriter.flush(); outputStream.close(); return true; } catch (FileNotFoundException e) { e.printStackTrace(); return false; } catch (UnsupportedEncodingException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 当未设置文件名时,随机生成一个文件名 * * @return default file name */ private static String getFileName() { Random random = new Random(); return FILE_PREFIX + Long.toString(System.currentTimeMillis() + random.nextInt(10000)).substring(4) + FILE_FORMAT; }}
JsonLog
JsonLog就更简单了,只有一个方法(本宝宝以前还以为Json打印会很麻烦呢)
public class JsonLog { public static void printJson(String tag, String msg, String headString) { String message; try { if (msg.startsWith("{")) {// 处理json对象 JSONObject jsonObject = new JSONObject(msg); message = jsonObject.toString(KLog.JSON_INDENT); } else if (msg.startsWith("[")) {// 处理json数组 JSONArray jsonArray = new JSONArray(msg); message = jsonArray.toString(KLog.JSON_INDENT); } else { message = msg; } } catch (JSONException e) { message = msg; } KLogUtil.printLine(tag, true);// 调用格式化方法 message = headString + KLog.LINE_SEPARATOR + message; String[] lines = message.split(KLog.LINE_SEPARATOR); for (String line : lines) { Log.d(tag, "║ " + line); } KLogUtil.printLine(tag, false);// 调用格式化方法 }}
XmlLog
两个方法:
public class XmlLog { /** * 打印xml * * @param tag log tag * @param xml xml content * @param headString 文件头 */ public static void printXml(String tag, String xml, String headString) { if (xml != null) { xml = XmlLog.formatXML(xml); xml = headString + "\n" + xml; } else { xml = headString + KLog.NULL_TIPS; } KLogUtil.printLine(tag, true); String[] lines = xml.split(KLog.LINE_SEPARATOR); for (String line : lines) { if (!KLogUtil.isEmpty(line)) { Log.d(tag, "║ " + line); } } KLogUtil.printLine(tag, false); } /** * @param inputXML xml content * @return 格式化后的xml String */ private static String formatXML(String inputXML) { try { Source xmlInput = new StreamSource(new StringReader(inputXML)); 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 (Exception e) { e.printStackTrace(); return inputXML; } }}
细心的你会发现,无论是Json形式还是XML形式,调用的都是系统原生的方法来处理数据,因此又时候对熟悉熟悉java(或android)提供的方法还是很方便的,哈哈。
上面用到的KLogUtil,如下:
public class KLogUtil { public static boolean isEmpty(String line) { return TextUtils.isEmpty(line) || line.equals("\n") || line.equals("\t") || TextUtils.isEmpty(line.trim()); } public static void printLine(String tag, boolean isTop) { if (isTop) { Log.d(tag, "╔═══════════════════════════════════════════════════════════════════════════════════════"); } else { Log.d(tag, "╚═══════════════════════════════════════════════════════════════════════════════════════"); } }}
核心文件KLog.java分析
给方法主要提供了类似于系统log方法的不同重载,比较简单,我这里要讲的是那个获取log具体有关的类名、方法名、行号等,与之相关的就是wrapperContent这个方法了。
private static String[] wrapperContent(int stackTraceIndex, String tagStr, Object... objects) { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); StackTraceElement targetElement = stackTrace[stackTraceIndex]; String className = targetElement.getClassName();// 得到类名 String[] classNameInfo = className.split("\\.");// 第一种形式 if (classNameInfo.length > 0) { className = classNameInfo[classNameInfo.length - 1] + SUFFIX; } if (className.contains("$")) {//第二种形式 className = className.split("\\$")[0] + SUFFIX; } String methodName = targetElement.getMethodName();//得到方法名 int lineNumber = targetElement.getLineNumber();//得到所在的行号 if (lineNumber < 0) { lineNumber = 0; } String tag = (tagStr == null ? className : tagStr); if (mIsGlobalTagEmpty && TextUtils.isEmpty(tag)) { tag = TAG_DEFAULT; } else if (!mIsGlobalTagEmpty) { tag = mGlobalTag; } // 得到消息主体 String msg = (objects == null) ? NULL_TIPS : getObjectsString(objects); String headString = "[ (" + className + ":" + lineNumber + ")#" + methodName + " ] "; return new String[]{tag, msg, headString}; }/** * 得到消息主体 * * @param objects 消息对象数组 * @return 消息主体字符串 */ private static String getObjectsString(Object... objects) { if (objects.length > 1) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("\n"); for (int i = 0; i < objects.length; i++) { Object object = objects[i]; if (object == null) { stringBuilder.append(PARAM).append("[").append(i).append("]").append(" = ").append(NULL).append("\n"); } else { stringBuilder.append(PARAM).append("[").append(i).append("]").append(" = ").append(object.toString()).append("\n"); } } return stringBuilder.toString(); } else { Object object = objects[0]; return object == null ? NULL : object.toString(); } }
分析完毕,是不是很简单,如果你看了这个库的代码,你会觉得我的分析都是多余的。
遇到的问题
在使用KLog打印json形式信息时,如果网络请求时异步的,会导致KLog.json打印的格式出现错乱,即一个结果还没有完全打印出来,里外一个就开始打印了,这个应该是并发导致的问题,之后我会在KLog的基础上对这个问题进行优化的。
0 0
- Android KLog源码分析
- Android专用Log打印工具KLog使用指南
- Android高效开发工具集合-KLog
- Android Log三方框架 KLog
- Android专用Log开源项目——KLog
- Android专用Log开源项目——KLog
- Android专用Log开源项目——KLog
- Android源码/框架源码分析
- Android 源码分析
- Android源码分析
- Android源码结构分析
- android launcher源码分析
- Android源码结构分析
- Android源码分析--STK
- android Button源码分析
- Android源码分析--彩信
- Android源码分析
- Android Gallery3D源码分析
- 火狐浏览器和谷歌浏览器主页被篡改恢复方法
- Longest Ordered Subsequence POJ
- 【MyBatis学习05】SqlMapConfig.xml文件中的配置总结
- CentOS 7.2 下使用yum命令安装MariaDB的记录
- PHP 基础知识
- Android KLog源码分析
- NAT模式下 宿主机与虚拟机不能Ping通的解决方式
- 中国游戏行业的展望
- 关于oj中经常碰到的输入不指定个数的输入问题
- 在 JavaScript 中 prototype 和 __proto__ 有什么区别
- Mac下安装MongoDB
- PHP——CURL模拟请求微信接口
- 常用工具
- MyGitHub