背景
在日常开发和调试过程中,我们经常需要用到logcat的日志来帮助我们定位问题,在生产环境也有类似的需求,当程序出现崩溃、anr等异常时,我们除了需要捕获异常日志外,往往需要抓取一段完整的logcat日志,给我们研发同学去分析定位问题,但是生产环境是复杂的,如果当发生异常后,设备很有可能被重启了,这时候我们的logcat日志往往就丢失了,无法事后再去抓取,所以这时候就需要我们在程序中提供一种自动抓取logcat日志的能力。
logcat的小知识点
-
设备的logcat日志是有一个最大的缓存限制的,默认是256k,可以通过开发者选项去调整这个大小,也可以通过logcat -G 10M 设置。
-
设备重启后,logcat的缓存会被清空。
-
在终端中使用adb logcat命令获取log和在程序中调用logcat的命令获取log是两回事,获取到的日志信息往往是不同的,往往是在终端中获取的日志更全一些。
-
自定义ROM修改默认的logcat缓存大小
// kernel\drivers\staging\android\logger.c
// 在create_log方法的第二个参数传入自动定义的大小就好
static int __init
logger_init(void) {
int ret;
ret = create_log(LOGGER_LOG_MAIN, 256 * 1024 );
if (unlikely(ret))
goto out;
ret = create_log(LOGGER_LOG_EVENTS, 256 * 1024);
if (unlikely(ret))
goto out;
ret = create_log(LOGGER_LOG_RADIO, 256 * 1024 );
if (unlikely(ret))
goto out;
ret = create_log(LOGGER_LOG_SYSTEM, 256 * 1024);
if (unlikely(ret))
goto out;
out:
return ret;
}
-
在程序中获取log需要加android.permission.READ_LOGS权限。
-
android 4.1之前版本通过申请READ_LOGS权限就可以读取其他应用的log了。但是谷歌发现这样存在安全风险,于是android 4.1以及之后版本,即使申请了READ_LOGS权限也无法读取其他应用的日志信息了。4.1版本中 Logcat的签名变为 “signature|system|development”了,这意味着只有系统签名的app或者root权限的app才能使用该权限。普通用户可以通过ADB查看所有日志。
-
手机root后很多情况下也是无法在程序中使用root权限的,因为adb shell 的进程和程序执行的进程不是同一个,因此无法使用su命令。
抓取logcat的方式
方式一:读取日志流自己写入到文件中
private static boolean catchLogcatLog(String crashLogCatPath) {
if(TextUtils.isEmpty(crashLogCatPath)){
return false;
}
java.lang.Process logcatProcess = null;
BufferedReader bufferedReader = null;
BufferedOutputStream bufferedOutputStream = null;
try {
/** 获取系统logcat日志信息 */
String[] running = new String[]{
"logcat"};
logcatProcess = Runtime.getRuntime().exec(running);
bufferedReader = new BufferedReader(new InputStreamReader(
logcatProcess.getInputStream()));
File file = new File(crashLogCatPath);
File parentFile = file.getParentFile();
if (!parentFile.exists() || !parentFile.isDirectory()) {
parentFile.mkdirs();
}
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file, true));
String line;
SimpleDateFormat simpleDateFormat = new