I am writing a gradle task to install an apk unto emulators before espresso tests are run.
This is the task I have so far.
task installButlerApk {
doLast {
println "Verifying test-butler installation in emulators"
final adb = "$android.sdkDirectory.absolutePath/platform-tools/adb"
final String[] split = ["$adb", "devices", "-l"].execute().text.split("\\r?\\n")
split.each {
if (it.isEmpty())
return;
println "Emulator: $it"
final emu = it.split("\\s")[0]
checks whether the APK is already installed
if (["$adb", "-s", "$emu", "shell", "pm", "list", "packages"].execute().text.contains(butlerPackage))
return;
final installResult = ["$adb", "-s", "$emu", "install", "$butlerApkPath"].execute().text
if (!installResult.contains("Success"))
println "Could not install APK. Install output:\n$installResult"
else
println "Installed $butlerApkPath in $emu successfully"
}
}
}
However when I run it via the terminal the task ends up freezing. I am not sure why. I did some research about it and at one point I thought the command that was being passed to ProcessGroovyMethods' execute was failing because it was being passed as a string (execute(String self)
) so I then used the array representation of execute (execute(String[] commandArray)
) to see if that would work but I am still ending up with the same result so I am just asking for someone who has experience writing these tasks to give me some assistance. So far, I am printing the result of the command and it hasn't shown any errors. It's just stuck at the building process for hours.
Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.
C:\Users\Joel\Documents\Projects\Forms>gradlew installButlerApk
Picked up _JAVA_OPTIONS: -XX:ParallelGCThreads=2
To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon:
https://docs.gradle.org/2.14.1/userguide/gradle_daemon.html.
Incremental java compilation is an incubating feature.
:app:installButlerApk
Verifying test-butler installation in emulators
Emulator: List of devices attached
> Building 0% > :app:installButlerApk
Well, this is expected behavior.
If you look at your output closely, you see
Emulator: List of devices attached
So following your code:
println "Emulator: $it"
outputs that line I quoted
final emu = it.split("\\s")[0]
takes the first space separated token which is List
checks whether the APK is already installed
this will not even compile, but I guess you just forgot the comment characters that you added in the question as explanation
if (["$adb", "-s", "$emu", "shell", "pm", "list", "packages"].execute().text.contains(butlerPackage))
return;
Now you execute adb -s List shell pm list
Executed manually this two times prints error: device not found
for me and then exits, so your contains
condition is false
and the return
is not done.
final installResult = ["$adb", "-s", "$emu", "install", "$butlerApkPath"].execute().text
Now you execute adb -s List install butler.apk
Executed manually this three times prints out error: device not found
, then one time - waiting for device -
and then sits there waiting until you cancel it, or a device with serial number List
becomes available which of course will never happen and thus your task hangs until you kill it.
You have to skip the header line when you work through the list of devices, as this is of course not a device.
Besides this, you can of course use the Groovy standard ways to execute external commands. Yet while in Gradle, I'd rather use the Gradle variants. If you only want to execute one thing it would be a task of type Exec
, if you want to execute multiple things like in your case, it is the Project.exec()
or Script.exec()
methods, so you would do something like
def output
new ByteArrayOutputStream().withStream { baos ->
exec {
executable android.adbExe
args "-s", emu, "shell", "pm", "list", "packages"
standardOutput baos
}.assertNormalExitValue()
output = baos.toString()
}
if (output.contains(butlerPackage)) {
return
}
exec {
executable android.adbExe
args "-s", emu, "install", butlerApkPath
}.assertNormalExitValue()