방법1) 터미널에서 adb 호출
방법2) code로 구현하여 호출
실시간 로그 저장하는 명령어
단, 계속 덮어쓰면서 백업됨(과부하의 원인)
adb logcat > /(파일경로)/testLog.txtoradb logcat -f /(파일경로)/testLog.txt
현재 출력된 로그만 저장하는 명령어
adb logcat -d > \(파일경로)\testLog.txtoradb 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
하위 내용은 설명위주로, 자세한 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 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");
}
성공실패여부를 판단하여 성공했을 경우에만 특정키워드 찾아서 저장
// 필터링한 로그 저장할 파일이름 지정
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);
}
현재 출력된 로그를 저장할 경로를 지정
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내용을 코드화 하는 공부를 한 적이 있어서 구현함에 있어 헤매이지 않고 잘 해결한 것 같다.