经理:Tank,我需要抓取应用的日志
我:你直接用AS的Logcat看不行吗?
经理:我是想在APP中直接查看日志,就像Logcat那样
我:明白了,就是做一个Logcat的功能呗
经理:是的
Okay,需求明朗了~搞一个APP来实时打印日志
首先,我们要知道如何获取日志呢?
if(你了解adb shell){
你会知道logcat这条命令;
}else{
我告诉你,我们可以通过这条命令打印日志;
}
我们先通过cmd执行下logcat看下效果:
从上面的效果图来看的话,我们是可以通过该指令实现想要的功能的,但是需要考虑几个问题:
1,频繁的读写,会不会导致ANR?
2,如此多的数据,如何展示?String会不会越界
针对第一个问题,我们可以创建一个子线程来进行日志的实时监听,然后通过Handler通知主线程进行日志的展示,为了方便大家熟悉Handler的原理,特附上链接
第二个问题,如果用一个String来保存所有的日志,百分百是会出现越界问题的。那么怎么解决?我选择用ScrollView中放一个竖直方向的LinearLayout,然后动态的添加TextView,每一行用一个String,这样总不会越界了吧哈哈。
问题解决之后,说干就干!
Step1:
界面布局,我们简单的创建一个ScrollView,内嵌一个LinearLayout,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/ll_content"
android:orientation="vertical"/>
</ScrollView>
Step2:
开启子线程,监听Logcat
private void initLogger() {
myThread = new Thread(){
@Override
public void run() {
super.run();
try {
Runtime runtime = Runtime.getRuntime();
proc = runtime.exec("su");
os = new DataOutputStream(proc.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
os.writeBytes("logcat -G 16m\n");
os.writeBytes("logcat\n");
os.flush();
String line;
currentTime = DateTimeUtil.getCurrentTimeMdHms(1000);
while ((line = in.readLine()) != null) {
if(needShow(line,currentTime)){
if(uiHandler!=null){
Message msg = new Message();
msg.obj = line;
uiHandler.sendMessage(msg);
}
}
}
} catch (IOException e) {
e.printStackTrace();
Log.i("wp error", e.toString());
}
}
};
myThread.start();
}
需要注意几个问题
1,这里要申请ROOT权限,因为在非ROOT手机中,代码执行logcat只会打印应用自身的日志
2,logcat -G是修改日志缓存大小,安卓默认的是很小的,很容易异常结束监听
3,刚执行logcat的时候,会有大量的数据同时打印,即使用Handler机制还是会出现ANR,因此需要做一下时间的过滤(needShow方法)
Step3:
在Handler中动态添加TextView
private Handler uiHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String content = (String)msg.obj;
if(!TextUtils.isEmpty(content) && llContent!=null){
TextView tv = new TextView(MainActivity.this);
llContent.addView(tv,0);
}
}
};
好了,至此我们便实现了一个简单的Logcat类似功能!