Ultimately I solved the problem by doing the following:
Inside my program, for calling
adb start-server
, I no longer useorg.apache.commons.exec.DefaultExecutor.execute("adb start-server")
nor Java'sRuntime.getRuntime().exec("adb start-server")
.
Instead, I usejava.lang.ProcessBuilder("adb start-server").inheritIO().start().waitFor()
. Note theinheritIO()
is added in Java 7 and allows for online reading of the started process stdout, among others.
EDIT TheinheritIO()
in Gradle has no effect when Gradle is called from CLI directly as opposed to being called by IntelliJ IDEA. See this question for details. Probably implementingStreamGobbler
as described here would fix the problem.In Gradle, instead of Gradle's application plugin's
run
task, I again useProcessBuilder
reusingrun
tasks variables. It looks like so:
apply plugin: 'java'
apply plugin: 'application'
sourceCompatibility = '1.7'
targetCompatibility = '1.7'
// configuration-time of the original run task
run {
main = com.example.MainClass; // without this, our custom run will try to run "null"
}
task myRun(dependsOn: build) {
// execution-time of our custom run task.
doFirst {
ProcessBuilder pb = new ProcessBuilder(tasks['run'].commandLine);
pb.directory(tasks['run'].workingDir);
// works when the gradle command is executed from IntelliJ IDEA, has no effect when executed from standalone CLI interface.
pb.inheritIO();
Process proc = pb.start();
proc.waitFor();
}
}
As for the reason of the strange behaviors, I don't have any definite answer, so I refrain from further comments.
EDIT 9 July 2013
This question seems to point out the answer to Question 2 is: on windows, the parent process waits for child process before it terminates. Unfortunately, the solutions proposed there do not work because of problem stated in Question 1.
Hope this helps,
Konrad