在工作中,会碰到一些设备上的原因,导致不能一直连着数据线抓logcat,这个时候需要一个能够离线抓取logcat的工具,有些芯片厂商提供的rom版本中自带这个工具,例如MTK的MTKLogger、高通的logcat(userdebug版本),这些工具都能够自动抓取logcat的内容
提示,制作抓取系统log的工具,需要将应用系统签名,否则只能拿到本应用的log
围绕抓取log过程中,产生了两个思路,但是思路一没有走通,如果想要直接使用的,请看思路二
思路一:logcat重定向,我们知道平时看logcat一般是在Android Studio中的界面中带工具可以查看,不过我们也可以在cmd中执行
adb logcat -v time > log.txt
这样就把logcat输出定向到了log.txt文件,不过这是在adb环境下通过连线输出到电脑上的重定向,跟机器本身的重定向不同,那么机器本身的重定向是怎么做的呢,我们进入到shell后执行下面的命令,其中&符号是linux中后台运行的命令
adb shell
logcat -v time > /sdcard/log.txt &
实际测试可以用,但是存在问题,重启后就又失效了,而我们有时候抓取log的时候就是为了抓启动界面的日志
所以我们需要一个apk执行这个命令,让apk在开机自启运行这段命令,有人会问那不是只能抓到这个apk启动之后的log么,其实logcat工具本身带有一些缓存,这也是我们有时候在调试应用的时候,出了问题之后再连上数据线也能看到出错日志的原因,所以利用这一点,再加上Runtime这个类,在apk中执行这段命令
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("logcat -v time > /sdcard/log.txt &");
但是这个时候我们就遇到了一个坑,Runtime.exec()不是命令解析器这段代码不会被执行,后面查了资料就有了思路二,我们自己读取logcat内容,自己写文件,而不是通过重定向让系统帮忙写,看来是不能省力了,还是要自己做
思路二:读取logcat中的内容,写入文件
如何直接读取logcat中的内容呢,使用下面的方法,使用这个代码的效果有点像在终端中输入命令cmd,结果会显示在终端中,不过这个不会显示在终端里面,需要我们自己读取里面的内容
ProcessBuilder processBuilder = new ProcessBuilder(new String[]{"sh", "-c", cmd});
processBuilder.redirectErrorStream(true);
先对processBuilder初始化,cmd中传入需要执行的命令
这里我们的cmd为
String cmd = "logcat -v time";
初始化之后,获取Process对象
try {
process = processBuilder.start();
new ReadThread(process.getInputStream(), "InputStream").start();
new ReadThread(process.getErrorStream(), "ErrorStream").start();
} catch (IOException e) {
e.printStackTrace();
}
读取线程我是这样写的
class ReadThread extends Thread {
InputStream inputStream;
int flag = OUTPUT;
String name = "None Name";
public ReadThread(InputStream inputStream, String name) {
this.inputStream = inputStream;
this.name = name;
}
@Override
public void run() {
super.run();
try {
byte[] buffer = new byte[1024 * 8];
int length = 0;
while (true) {
while ((length = inputStream.read(buffer)) != -1) {
byte[] tmp = new byte[length];
System.arraycopy(buffer, 0, tmp, 0, length);
Message message = handler.obtainMessage();
message.what = flag;
message.obj = new String(tmp);
handler.sendMessage(message);
buffer = new byte[1024 * 8];
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
这就是读取logcat内容并写入文件的过程,做成app后还有很多工作,例如需要请求存储权限、开机自启、空间满了之后怎么处理、如何设定log大小循环写入等等等,这个属于业务上的内容了,就不另外扩展了
还有一点需要注意的是,需要设置systemuid以及系统签名