Java程序执行终端命令异常:Android Monkey测试崩溃报告无法写入文件
Hey there! Let's figure out why your third command—extracting crash reports to a file—isn't playing nice when called from your Java program. This is almost always tied to permission issues, wonky command syntax in Java, or where your process is trying to write the file. Let's break down the most common fixes:
1. Fix Permission Problems First
When your Java app runs terminal commands, it uses the permissions of the Java process itself—not your personal user account (especially if it's running as a service or in a restricted environment).
- If you're trying to write to a system directory on the Android device (like
/system/) or a protected local folder (thinkC:\Program Fileson Windows), you'll get a permission denied error every time. - Solution: Use a directory you know has write access:
- On the Android side: Stick to
/sdcard/(just make sure your app holds theWRITE_EXTERNAL_STORAGEpermission, or use scoped storage if you're targeting Android 10+). - On your local machine: Write to your user's home folder—something like
~/crash_reports.txt(macOS/Linux) or%USERPROFILE%\crash_reports.txt(Windows).
- On the Android side: Stick to
2. Fix Command Syntax Escaping
Java's Runtime.exec() doesn't handle shell redirects (like >) the same way a terminal does if you pass the whole command as a single string. It'll treat > and the filename as arguments to logcat instead of telling the shell to write output to a file.
- Bad approach:
Runtime.getRuntime().exec("adb logcat -d *:E > crash_log.txt"); - Good fixes:
Either useProcessBuilderwith a shell to handle the redirect:
Or better yet, capture the log output directly in Java and write it to a file—this gives you more control and avoids shell quirks:ProcessBuilder pb = new ProcessBuilder("sh", "-c", "adb logcat -d *:E > /sdcard/crash_report.txt"); pb.start();// Run logcat and capture output Process logcatProcess = Runtime.getRuntime().exec("adb logcat -d *:E"); BufferedReader logReader = new BufferedReader(new InputStreamReader(logcatProcess.getInputStream())); BufferedWriter fileWriter = new BufferedWriter(new FileWriter("/path/to/your/local/crash_report.txt")); String line; while ((line = logReader.readLine()) != null) { fileWriter.write(line); fileWriter.newLine(); } // Clean up streams logReader.close(); fileWriter.close();
3. Fix Working Directory Mismatches
If you're using a relative path (like just crash_report.txt), Java will try to create the file in its current working directory—which might not be where you expect (like your project's root or a temp folder).
- Solution: Use an absolute path, or set the working directory explicitly in
ProcessBuilder:ProcessBuilder pb = new ProcessBuilder("sh", "-c", "adb logcat -d *:E > crash_report.txt"); pb.directory(new File("/your/desired/write/directory")); // Point to the right folder pb.start();
4. Make Sure the Monkey Test Finishes First
Sometimes the log extraction runs too soon—before the Monkey test has actually crashed the app or finished running. Adding a wait ensures you capture all relevant logs.
- Solution: Wait for the Monkey process to complete before running the logcat command:
// Start Monkey test Process monkeyProcess = Runtime.getRuntime().exec("adb shell monkey -p com.your.app 1000"); monkeyProcess.waitFor(); // Pause until Monkey finishes // Now extract the crash logs Process logcatProcess = Runtime.getRuntime().exec("adb logcat -d *:E > /sdcard/crash_report.txt");
5. Refine Your Logcat Filter
Double-check that your logcat command is actually capturing crash logs. Using *:E grabs all errors, but Android crashes usually show up under the AndroidRuntime tag. Try a more targeted filter to make sure you're getting what you need:
adb logcat -d AndroidRuntime:E *:S
Quick Debugging Tips
- Test the command manually in a terminal first. If it works there, the problem is definitely in how Java is executing it.
- Check for error messages from the process—read the error stream to see if there are permission denials or syntax issues:
Process process = pb.start(); BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); String errorLine; while ((errorLine = errorReader.readLine()) != null) { System.err.println("Command failed with: " + errorLine); }
内容的提问来源于stack exchange,提问作者afc

