Adroid Logcat에 출력된 전체 로그를 저장 또는 조회 후 특정키워드 필터링하여 별도 저장하기


방법1) 터미널에서 adb 호출
방법2) code로 구현하여 호출



터미널에서 adb 호출

실시간 로그 저장하는 명령어
단, 계속 덮어쓰면서 백업됨(과부하의 원인)
adb logcat > /(파일경로)/testLog.txt or adb logcat -f /(파일경로)/testLog.txt

현재 출력된 로그만 저장하는 명령어
adb logcat -d > \(파일경로)\testLog.txt or adb logcat -d -f \(파일경로)\testLog.txt

현재 출력된 로그의 특정 키워드 필터링하여 저장하는 명령어
환경에 따라서 grep, find, findstr 사용
adb logcat -d | grep "keyword" > \(파일경로)\testLog.txt
adb logcat -d | find "keyword" > \(파일경로)\testLog.txt
adb logcat -d | findstr "keyword" > \(파일경로)\testLog.txt
or
adb logcat -d | grep "keyword" -f \(파일경로)\testLog.txt
adb logcat -d | find "keyword" -f \(파일경로)\testLog.txt
adb logcat -d | findstr "keyword" -f \(파일경로)\testLog.txt

버퍼에 저장된 모든 로그를 지우는 명령어
이전 로그를 삭제해 새 로그만 기록되도록 설정
adb logcat -c > /(파일경로)/testLog.txt




java코드로 구현하기

하위 내용은 설명위주로, 자세한 code는 github 참고

환경설정 : Manifest 권한

[로그 데이터를 읽기 위한 권한]
권한 주지 않으면 현재 package에서 출력된 내용만 저장됨
<uses-permission android:name="android.permission.READ_LOGS"/>

[외부 저장소 접근 권한]
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />




방법1: 각각 파일 저장하는 코드

현재 출력된 로그를 저장할 경로를 지정

path = context.getFilesDir().getPath(); // "/data/user/0/(packageName)/files"

1) 현재 출력된 로그 저장하기

저장을 원하는 경로에 폴더존재여부를 판단한 뒤 폴더생성 및 권한 부여

File logDirectory = new File(path);

if (!logDirectory.exists()) {
	logDirectory.mkdirs();
	LogUtil.d("logDirectory 생성!");
}
setFilePermissions(logDirectory); // 권한 부여

권한 부여 방법

private static void setFilePermissions(File file) {
// 파일에 읽기, 쓰기, 실행 권한 부여
	file.setWritable(true, false);
	file.setReadable(true, false);
	file.setExecutable(true, false);
}

저장하고자 하는 파일이름 지정

String logFileName = "log.txt";
File logFile = new File(logDirectory, logFileName);

logcat을 파일에 저장

adb logcat -d -f \(파일경로)\testLog.txt과 동일한 내용

Process process = Runtime.getRuntime().exec("logcat -d -f " + logFile); 

성공실패 여부를 판단하고 싶다면?!

프로세스가 종료될 때까지 기다린 후 에러 메시지를 출력하기

int exitCode = process.waitFor(); // 프로세스가 종료될 때까지 기다림

// 에러 메시지 출력
if (exitCode != 0) {
	BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
	StringBuilder errorMsg = new StringBuilder();
	String line;
	while ((line = errorReader.readLine()) != null) {
		errorMsg.append(line).append("\n");
	}
	errorReader.close();
	LogUtil.e("sync command failed with exit code: " + exitCode);
	LogUtil.e("Error message: " + errorMsg.toString());
} else {
	LogUtil.i("sync command executed successfully");
	}

2) 저장된 내용을 기반으로 특정키워드를 필터링 저장

성공실패여부를 판단하여 성공했을 경우에만 특정키워드 찾아서 저장

// 필터링한 로그 저장할 파일이름 지정
String logFileName = "logFilter.txt";
File outputFile = new File(path, logFileName);

try (BufferedReader reader = new BufferedReader(new FileReader(logFile.getAbsolutePath()));
FileWriter fileWriter = new FileWriter(outputFile, true)) {
	String line;
	while ((line = reader.readLine()) != null) {
		if (line.contains(keyword)) {
			fileWriter.write(line + System.lineSeparator()); // 검색 문자열이 포함된 라인 저장
		}
	}

} catch (IOException e) {
	//            e.printStackTrace();
	LogUtil.e("Error reading file : " + e);
}



방법2: 필터링한 파일만 저장하기

현재 출력된 로그를 저장할 경로를 지정

path = context.getFilesDir().getPath(); // "/data/user/0/(packageName)/files"

필터링한 로그파일 저장 경로 지정

저장을 원하는 경로에 폴더존재여부를 판단한 뒤 폴더생성 및 권한 부여

File logDirectory = new File(path);

if (!logDirectory.exists()) {
	logDirectory.mkdirs();
	LogUtil.e("logDirectory 생성!");
}
setFilePermissions(logDirectory);

현재 출력된 로그 조회

adb logcat -d과 동일한 내용

Process process = Runtime.getRuntime().exec("logcat -d"); // 현재 출력된 로그 조회

필터링한 로그 저장할 파일이름 지정

String logFileName = "onlyFilterLog.txt";
File logFile = new File(logDirectory, logFileName);

로그에서 특정 키워드가 포함된 줄만 필터링하여 파일에 기록

 try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); FileWriter writer = new FileWriter(logFile, true)) { // true로 append 모드 설정
	String line;
	while ((line = reader.readLine()) != null) {
		if (line.contains(keyword)) {
			writer.write(line + System.lineSeparator()); // 각 줄 끝에 개행 문자 추가 = "\n"
		}
	}
}

성공실패 여부를 판단하고 싶다면?!

프로세스가 종료될 때까지 기다린 후 에러 메시지를 출력하기

int exitCode = process.waitFor(); // 프로세스가 종료될 때까지 기다림

// 에러 메시지 출력
if (exitCode != 0) {
	BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
	StringBuilder errorMsg = new StringBuilder();
	String line;
	while ((line = errorReader.readLine()) != null) {
		errorMsg.append(line).append("\n");
	}
	errorReader.close();
	LogUtil.e("sync command failed with exit code: " + exitCode);
	LogUtil.e("Error message: " + errorMsg.toString());
} else {
	LogUtil.i("sync command executed successfully");
}


마치며

경로나 버전에 따라 추가적인 권한이 필요할 수 있으나, 그 부분만 주의한다면 code로 충분히 구현할 수 있는 내용이다. 터미널을 사용하여 adb 호출시 편리함이 있지만, code내 구현해야 한다면, 이 코드가 큰 도움이 될 것이다. 이 내용 이전에, adb내용을 코드화 하는 공부를 한 적이 있어서 구현함에 있어 헤매이지 않고 잘 해결한 것 같다.

profile
숲을 그리는 개발자

0개의 댓글