android日志保存

在Android应用中,日志通常在签名版本中关闭,仅用于发送崩溃日志。但当需要分析用户数据异常时,可通过隐藏功能让用户发送日志到服务器。本文介绍了如何使用logcat命令记录日志,但原始方法会捕获所有应用的日志,而不仅仅是本应用的。为解决此问题,提出了使用logcat结合grep过滤特定应用日志的方法,通过将InputStream写入文件实现更精确的日志保存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在我们发布的签名应用中,日志都是关闭的,通常只会做发送崩溃日志的功能。但在某些场景中,如用户数据有异常等情况,需要对具体日志进行分析,但这是我们无法获取日志,此时就通过某个隐藏功能,让用户可以在执行这个操作后,能够将日志发送到服务器,以便开发人员进行分析。

在日志记录中,通常会使用logcat命令来进行日志的记录,关键代码如下:

private void collectOld(){
		/* Logcat命令列表
			Option Description 
			-b <buffer> 加载一个可使用的日志缓冲区供查看,比如event 和radio . 默认值是main 。具体查看Viewing Alternative Log Buffers. 
			-c 清楚屏幕上的日志. 
			-d 输出日志到屏幕上. 
			-f <filename> 指定输出日志信息的<filename> ,默认是stdout . 
			-g 输出指定的日志缓冲区,输出后退出. 
			-n <count> 设置日志的最大数目<count> .,默认值是4,需要和 -r 选项一起使用。 
			-r <kbytes> 每<kbytes> 时输出日志,默认值为16,需要和-f 选项一起使用. 
			-s 设置默认的过滤级别为silent. 
			-v <format> 设置日志输入格式,默认的是brief 格式,要知道更多的支持的格式,参看Controlling Log Output Format 
		*/
		String logFileName = sdf.format(new Date()) + ".log";// 日志文件名称
		List<String> commandList = new ArrayList<String>();
		commandList.add("logcat");
		//设置输入文件的路径,并将路径保存到SharedPreferences中
		commandList.add("-f");
		String realLogPath = getLogPath();
		//设置输入格式
		commandList.add(realLogPath);
		commandList.add("-v");
		commandList.add("time");
		//过滤所有TAG的级别V以上的信息,如果需指明TAG,无论级别,则必须在指明后增加*:S命令
		commandList.add("*:V");
		try {
			process = Runtime.getRuntime().exec(
					commandList.toArray(new String[commandList.size()]));
			recordLogServiceLog("start collecting the log,and log name is:"+logFileName);
			 process.waitFor();
		} catch (Exception e) {
			recordLogServiceLog("CollectorThread == >" + e.getMessage());
		}
	}

经过测试,上述代码确实运行正常,但也有个非常明显的问题。它会将所有日志记录下来,包括本应用的和其他应用所产生的,这对我们的日志查看非常不利,因为我们只需要看到本应用的日志即可。在命令行中使用logcat,我们可以通过grep根据应用的PID来实现过滤本应用的日志,但在logcat命令中,logcat -f 却无法使用grep来进行过滤,因此,再使用logcat -f来保存日志,并不符合需求。经过测试,使用logcat + grep来获得InputStream,通过手动写入文件的方式,而非通过logcat -f可以实现这种过滤效果。具体的实现为:

private void collectNew(){
		mPID = android.os.Process.myPid()+"";
		String realLogPath = getLogPath();
		SharedPreferences sp = getSharedPreferences("logserver", MODE_PRIVATE);
		SharedPreferences.Editor editor = sp.edit();
		editor.putString("log_path", realLogPath);
		editor.commit();
		SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm:ss:SSS");
		try {
			File file = new File(realLogPath);
			String cmds = "logcat *:v | grep \"(" + mPID + ")\"";
			logcatProc = Runtime.getRuntime().exec(cmds);
			mReader = new BufferedReader(new InputStreamReader(logcatProc.getInputStream()), 1024);
			out = new FileOutputStream(file);
			String line = null;
			while (mRunning && (line = mReader.readLine()) != null) {
				if (!mRunning) {
					break;
				}
				if (line.length() == 0) {
					continue;
				}
				if (out != null && line.contains(mPID)) {
					 out.write((sdf.format(new Date()) + " " + line + "\n").getBytes());
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (logcatProc != null) {
				logcatProc.destroy();
				logcatProc = null;
			}
			if (mReader != null) {
				try {
					mReader.close();
					mReader = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (out != null) {
				try {
					out.close();

				} catch (IOException e) {
					e.printStackTrace();

				}
				out = null;
			}
		}
	}

经过验证,新的方法实现了只记录本应用日志到指定文件的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值