ZeusLog
0x00 解决问题
网络请求查看比较麻烦,需要fiddler/charles代理,再格式化json。手机端可以像打印日志一样打印json格式化后的log
系统Log比较挫,限制多多。优化系统控制台log打印
项目地址 https://github.com/xsfelvis/ZeusLog
0x01 ZeusLog
主要分为两大块,移动端Log和控制台Log,先上图
移动端
主要支持
显示当前Actvity的名称
显示所需打印网络请求的内容,内容部分透传点击事件,不影响app使用
右边有一个长条控制区域,可以滑动联动内容区域,便于阅读长的网络请求
具体如下
【黄色区域】 当前Actvity名称
【红色区域】 log日志开启或者关闭,关闭后右边控制区域也随之消失,只有当前的Activity名称,如下
【橙色区域】 网络请求格式化显示区域,该部分透传所有点击事件,从而使整个App使用不受影响
【绿色区域】 自定义sideBar,滑动该区域控制橙色区域长文本滚动阅读
技术点:
没有采用window去实现,原因很简单,兼容性不好,现在各大厂商对自己的windows权限管理都很紧,而且正好尝试一下自定义view+事件分发,有了想法,一时技痒,就撸一个呗,当然你也可以有其他更好的思路,也可以跟我交流。
主要采用了自定义viewgroup+自定义view
SideDragBar【绿色部分】,通过橙色部分显示内容,透传点击事件从而不影响用户对app操作,SideDragBar控制内容区域的滚动,从而不影响内容区长文本的阅读。
几个关键点:
- 附着到当前Activity屏幕
获取屏幕的content区域内容,然后将我们的自定义viewgroup add进去
1 | ViewGroup rootView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT); |
首先我们需要知道android中window的位置
- 透传文本区域的点击事件
我们希望屏幕日志只是给用户用来查看,而不要影响用户对app的操作,但是也要对长文本支持,这样采用重写ScrollView包裹一个textView的方法来解决这个问题,这个ScrollView的拦截事件方法均被重写
1 |
|
这样这个scrollview就可以透传了,
1 |
|
- 长日志如何滑动查看
这里思考了一会,最后给出的解决方案就是在边栏加一个自定义view SideDragBar【绿色部分】
通过重写dispatchTouchEvent,记录滑动变化,然后使用控制传入的scrollview滚动
1 |
|
总之就是通过重写scrollview使得控制滚动,从而解决这个问题
4.格式化json数据
关于这个,刚开始在网上找了一下,很多都是直接for循环一个一个字符的去解析,感觉实在不够优雅,而且效率也很低,其实JSONObject、JSONArray就可以解决这个问题
1 |
|
控制台
控制台有一些比较全的Log库,如orhanobut/logger、JakeWharton/timber等,感觉这些库写的都很重,当然功能很全,个人不太不喜欢他们打印log格式化方式,而且也想看看具体原理还有也不想增加无需求的功能,如xml格式化等,最终自己搓了一个支持基本log+多参数+json格式,具体如下:
支持显示行号
支持显示Log所在函数名称
支持无Tag快捷打印
支持在Android Studio开发IDE中,点击函数名称,跳转至Log所在位置
支持JSON字符串解析打印
支持无限长字符串打印,无Logcat4000字符限制
支持变长参数,任意个数打印参数
支持设置全局Tag
基本tag
无tag显示当前类名
格式化输出json
多参数log
几个关键点
- 显示行号、函数名
这个需要使用到Thread.currentThread().getStackTrace()返回的是一个StackTraceElement数组,内容为调用函数堆栈,并且以调用层级关系保存。android中对应返回值数组是19个,而且最终都是调用
1 | dalvik.system.NativeStart.main(Native Method) |
有兴趣的可以断点看下,其实日志打印工具类实现都离不开它的应用,然后获取对应index的StackTraceElement你就可以获取当前行号,类名,部分代码如下
1 | StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); |
- log长字符的限制
先介绍下Android中Log的实现结构

可以看出大致过程 App通过util.log.产生日志->JVM->JNI(Native C)调用->log_write的sys_call()->logger驱动->dispatch分发给订阅者,android打印受限问题就出在这个Logger驱动上
1 |
|
可以看出,系统的显示单条Log长度是有限制的4*1024字符长度,那么我们打印日志的时候可以对症下药,在写自己的log日志时可以对msg做下处理,采取分段打印
1 |
|
0x02 How to Use
引入这个库 或者aar
移动端Log使用很简单,需要在你想打印的地方,调用如下API即可
ZeusMobileView.startZeus(MainActivity.this).setJsonStr(JSON_LONG);
控制台Log 需要先初始化安全等级
ZeusLog.init(BuildConfig.DEBUG); 表示仅仅在debug包下打印日志,如果不初始化也可使用,但是需要注意release包保护
然后如同使用系统API一样使用即可
不带tag
ZeusLog.v(LOG_MSG);
ZeusLog.d(LOG_MSG);
ZeusLog.i(LOG_MSG);
ZeusLog.w(LOG_MSG);
ZeusLog.e(LOG_MSG);
ZeusLog.a(LOG_MSG);
带tag
ZeusLog.v(TAG, LOG_MSG);
ZeusLog.d(TAG, LOG_MSG);
ZeusLog.i(TAG, LOG_MSG);
ZeusLog.w(TAG, LOG_MSG);
ZeusLog.e(TAG, LOG_MSG);
ZeusLog.a(TAG, LOG_MSG);
json格式化
- ZeusLog.printJsonStr(JSON);
多个参数
ZeusLog.v(TAG, LOG_MSG, “params1”, “params2”, this);
ZeusLog.d(TAG, LOG_MSG, “params1”, “params2”, this);
ZeusLog.i(TAG, LOG_MSG, “params1”, “params2”, this);
ZeusLog.w(TAG, LOG_MSG, “params1”, “params2”, this);
ZeusLog.e(TAG, LOG_MSG, “params1”, “params2”, this);
ZeusLog.a(TAG, LOG_MSG, “params1”, “params2”, this);







