I was struggling with a problem where I wanted to use Gradle to execute .bat script after .apk build that signed the application with platform key, and reinstalled it on the device.
Folder structure
File instruction.bat content
java -jar "..\app\build\outputs\apk\signapk.jar"
"..\app\build\outputs\apk\platform.x509.pem"
"..\app\build\outputs\apk\platform.pk8"
"..\app\build\outputs\apk\app-debug.apk"
"..\app\build\outputs\apk\signed.apk"
adb install -r "..\app\build\outputs\apk\signed.apk"
adb shell am start -n
com.your.package/com.your.package.MainActivity
Add this to your build.gradle -
task signAndInstall(type: Exec) {
def finalPath = projectDir.toString() + '\build\outputs\apk\instruction.bat'
commandLine = [finalPath] }
android {
applicationVariants.all { variant ->
variant.assemble.doLast {
signAndInstall.execute()
}
} }
I have a task that is supposed to run a shell script. In Gradle, I have defined the following:
defaultTasks 'renaming'
... some other stuff goes here ...
task renaming(type: Exec) {
commandLine 'sh', 'src/main/bin/rename.sh'
}
I have the shell script under my module in src/main/bin/
However, it is not getting run (for test purposes, the shell creates a directory called "asfasf"). How can I fix this?
As you give sh a relative path, it is resolved against the working directory of the Exec task. Either set the working directory for the Exec task or use file('src/main/bin/rename.sh') as second argument to commandLine.
I'm attempting to add a pre-pre-build shell script to my gradle/Android-Studio build. I've added the following to app/build.gradle:
task prePreBuild << {
commandLine 'ls'
}
preBuild.dependsOn prePreBuild
When I invoke my build with ./gradlew assembleDebug I get the following error:
Could not find method commandLine() for arguments [ls] on project ':app'
If I replace the commandLine line with something like println 'Hello' then it works fine, and I can see the output from my new task.
I searched for other mentions of "Could not find method commandLine" and found nothing. What is the correct way to invoke a shell script from this gradle task?
You need to indicate the type of the task or use the exec block:
task execute(type: Exec) {
}
or
exec {
}
You can find more info on https://docs.gradle.org/current/dsl/org.gradle.api.tasks.Exec.html
I'm almost certain i am overlooking something.
I have an android gradle project with a build.gradle file. Inside here, I specify the task:
task doSomething(type: Exec) {
println("okay clearly you have got to be getting in here")
commandLine 'sh /Users/dzt/Desktop/create_a_file_on_desktop.sh'
}
and that doesn't run at all. the shell file just literally does:
#!/bin/sh
echo "hi" > /Users/dzt/Desktop/i_am_a_byproduct.txt
and i ran chmod u+x on it so it is executable (i double checked on regular bash shell).
I also tried to use the groovy command:
"cd ../ && sh /Users/dzt/Desktop/create_a_file_on_desktop.sh".execute()
which does not work either. I'm a little stumped. i do NOT see the output file. however, i do see my print statement in the gradle console.
What is going on here?
** EDIT **
okay, i drilled it down more ->
cd ../ does not work at all. why is this? i need to use a relative path, at least relative to this directory
The call must be
commandLine 'sh', '/Users/dzt/Desktop/create_a_file_on_desktop.sh'
or else this is considered one command. But you want to start the sh with the script as param. On the other hand, since you have set the execute-bit, you can as well just call the shell script directly.
See http://gradle.org/docs/current/dsl/org.gradle.api.tasks.Exec.html
Running cd like you want with cd ../ && sh script does also not work like this, since && is a shell script command. If you want to run like this, you have to run the shell and make it run as a command. E.g.
commandLine 'sh', '-c', 'cd ~/scripts && sh myscript.sh'
Gradle does not allow cd command for some reason. some commands just do NOT work using groovy.
instead, i used cd inside my shell script. that seems to work just fine.
First, you have to put in the root level gradle.build file. The you need to write it like this, to actually be able to execute the task.
task doSomething << {
group 'yourGroupName'
description 'Runs your bash script'
exec {
workingDir "$projectDir/../pathto/"
commandLine 'bash', '-c', './bashscript.sh'
}
}
Then you can execute with: ./gradlew -q doSomething. In this case I used bash, but you can use any supported scripting shell, like sh, perl, python etc.
What the question says really - can you issue any commands directly to gradlew via the command line to build, package and deploy to a device?
$ gradle installDebug
This will push the debug build apk to device, but you have to manually start the application.
Since you are using Gradle, you could simple add your own task in build.gradle
task appStart(type: Exec, dependsOn: 'installDebug') {
// linux
commandLine 'adb', 'shell', 'am', 'start', '-n', 'com.example/.MyActivity'
// windows
// commandLine 'cmd', '/c', 'adb', 'shell', 'am', 'start', '-n', 'com.example/.MyActivity'
}
then call it in your project root
$ gradle appStart
Update:
If you are using applicationIdSuffix ".debug", add .debug to the appId only but leave the activity untouched:
'com.example.debug/com.example.MyActivity'
1. Build project, install generated apk to device
# at the root dir of project
$ gradle installDebug
2. Open app on device
$ adb shell am start -n yourpackagename/.activityname
One line sentence:
Build project & Install generated apk & Open app on device
$ ./gradlew installDebug && adb shell am start -n com.example/.activities.MainActivity
There are three commands to accomplish this:
./gradlew assembleDebug #To build the project
adb install -r ./app/build/outputs/apk/app-debug.apk #To install it to the device
adb shell am start -n $PACKAGE/$PACKAGE.$ACTIVITY #To launch the application in the device, where $PACKAGE is the development package and $ACTIVITY is the activity to be launched (the launcher activity).
I've been writing a bash script to do this, with other few features.
A more flexible way to do it is by using monkey:
task runDebug (type: Exec, dependsOn: 'installDebug') {
commandLine android.getAdbExe().toString(), "shell",
"monkey",
"-p", "your.package.name.debugsuffix",
"-c", "android.intent.category.LAUNCHER", "1"
}
Some advantages to this method:
getAdbExe doesn't require adb to be on the path and uses the adb version from the sdk pointed to in local.properties.
The monkey tool allows you to send a launcher intent, so you aren't required to know the name of your activity.
Build -> uninstall old verion -> install new version -> run application.
echo "Build application" && ./gradlew clean build &&
echo "Uninstall application" && adb uninstall [application package] &&
echo "Install application" && adb -d install app/build/outputs/apk/<build type>/[apk name].apk echo "Run application" &&
adb shell am start -n [application package]/.[application name]
Or if you want install and run application in debug type.
./gradlew installDebug && adb shell am start -n [application package]/.[application name]
I wrote this task to be able to install and also open the application on the device. Since I had multiple buildTypes and flavors with different application ids, it was not feasible to hard code the package name. So I wrote it like this instead:
android.applicationVariants.all { variant ->
task "open${variant.name.capitalize()}" {
dependsOn "install${variant.name.capitalize()}"
doLast {
exec {
commandLine "adb shell monkey -p ${variant.applicationId} -c android.intent.category.LAUNCHER 1".split(" ")
}
}
}
}
This would give you open{variant} for every install{variant} task you already have.
task appStart(type: Exec, dependsOn: 'installDebug') {
commandLine android.adbExe, 'shell', 'am', 'start', '-n', 'com.example/.MyActivity'
}