Adroid Logcat에 출력된 전체 로그 조회 후 특정패키지 필터링하여 별도 저장하기


이전에, Android log 저장하기 + 특정키워드 필터링하는 방법에 대해서 정리했다. 이어 package:(패키지명)으로 로그 조회 및 저장하는 방법을 알아보려 한다.

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



터미널에서 adb 호출

특정 패키지를 조회하는 방법은 2가지가 있다.
PID를 조회하여 찾는 방법과 PID를 자동으로 가져오는 방법이다.

앱 패키지 이름의 PID를 조회하는 명령어
adb shell pidof (패키지명)

조회한 PID를 사용하여 log저장하는 명령어
환경에 따라서 grep, find, findstr 사용
PID 앞에 띄어쓰기 필수!
adb logcat -d | grep " (PID)"
adb logcat -d | find " (PID)"
adb logcat -d | findstr " (PID)"

PID를 자동으로 가져와서 log저장하는 명령어
adb logcat -d --pid=$(adb shell pidof (패키지명)) > \(파일경로)\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" />




파라미터로 패키지명을 받아 조회 후 저장하기

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

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

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

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);

해당 패키지의 PID 얻기

adb shell pidof (패키지명)과 동일한 내용

Process getPidProcess = Runtime.getRuntime().exec("pidof " + packageName);
BufferedReader pidReader = new BufferedReader(new InputStreamReader(getPidProcess.getInputStream()));
String pid = pidReader.readLine(); // 여러 PID가 나올 수 있지만, 첫 번째만 사용
pidReader.close();

PID 조회

Android Studio에서 터미널에서 조회하는 것과 다르게 현재 사용중인 앱인 경우만 PID를 조회할 수 있다. 이를 대처하기 위하여, 터미널로 PID를 조회 후 파라미터로 사용하도록 하였다.

사용중인 앱이 아니라면, 터미널로 조회한 PID를 파라미터로 넣기
adb shell pidof (패키지명)

if (pid == null || pid.isEmpty()) {
	LogUtil.e("해당 앱의 PID를 찾을 수 없음!");
	LogUtil.e("packageName = " + packageName + "PID로 지정하여 재조회!");
	// packageName을 pid로 보낸다면 가능!
	pid = packageName;
}

PID(패키지명) 필터링

adb logcat -d | grep " (PID)"과 동일한 내용

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

logcat을 파일에 저장

int cnt = 0;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
 BufferedWriter writer = new BufferedWriter(new FileWriter(logFile, true))) {
	String line;
	while ((line = reader.readLine()) != null) {
	cnt++;
	writer.write(line);
	writer.newLine();
	}
}
LogUtil.d(cnt + "개 확인 >> findPackage DONE!");

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

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

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

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");
}


마치며

키워드로 조회하여 저장하는 방법은 Android Studio내에서 Logcat 필터링 한 것과 100% 같지 않는 현상을 발견했다. 이유는 터미널로 필터링한 경우 단순 텍스트 매칭을 기반으로 하지만, Android Studio는 더 정교한 매칭으로 출력되기 때문이라고 한다. 이에 둘사이의 정확도 높은 로그를 얻고 싶어서 알아보다가 패키지명으로 조회하는 방법을 알아냈고 매칭이 100%였다.
키워드로 조회하는 방법도 로그를 읽는데에는 큰 문제는 없지만, 필요한 상황에 따라 활용하면 좋을 것 같다.


profile
숲을 그리는 개발자

0개의 댓글