이전에, Android log 저장하기 + 특정키워드 필터링하는 방법에 대해서 정리했다. 이어 package:(패키지명)으로 로그 조회 및 저장하는 방법을 알아보려 한다.
방법1) 터미널에서 adb 호출
방법2) code로 구현하여 호출
특정 패키지를 조회하는 방법은 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
하위 내용은 설명위주로, 자세한 code는 github 참고
[로그 데이터를 읽기 위한 권한]
권한 주지 않으면 현재 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);
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();
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;
}
adb logcat -d | grep " (PID)"과 동일한 내용
Process process = Runtime.getRuntime().exec("logcat -d --pid=" + pid);
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%였다.
키워드로 조회하는 방법도 로그를 읽는데에는 큰 문제는 없지만, 필요한 상황에 따라 활용하면 좋을 것 같다.