I use bugsnag to monitor crashes in my Android app.
I also use ProGuard when I compile a release version.
I need to upload the mapping.txt file that is generated in build/outputs/mapping/prod/release folder of my project.
When I run this command in (Windows) command line:
curl https://upload.bugsnag.com -F proguard=#C:/mapping.txt -F apiKey=1111111111111111111111 -F versionCode=11111111 -F appId=com.my.package -F versionNumber=1.0.0
The file is uploaded and everything works.
All I need is to add a task to gradle so it uploads the file once its ready.
So once I compile the project for release, the mapping.txt file gets generated and once its ready, upload the file using this curl command (which is taken from bugsnag's web site by the way).
I tried many variations. The current one compiles but I do not think the file is being uploaded... I can't see any indication that it actually happened.
This is the code I currently use:
task uploadPro(type: Exec) {
logger.error("inside upload task")
commandLine 'cmd', '/c', 'curl', 'https://upload.bugsnag.com', '-F','proguard=#build/outputs/mapping/prod/release/mapping.txt', '-F', 'apiKey=1111111111111111111111', '-F', 'versionCode=111111', '-F', 'appId=com.my.package', '-F', 'versionNumber=1.0.0'
standardOutput = new ByteArrayOutputStream()
doLast {
String output = standardOutput.toString()
logger.info(output);
}
}
I also tried using this:
def p = ['cmd', '/c', 'curl', 'https://upload.bugsnag.com', '-F', 'proguard=#build/outputs/mapping/prod/release/mapping.txt', '-F', 'apiKey=11111111111111111111111', '-F', 'versionCode=1111111', '-F', 'appId=com.my.package', '-F', 'versionNumber=1.0.0'].execute()
The way I call this task is by using this command:
tasks.getByName("assembleRelease").finalizedBy(uploadPro)
Im really not sure how to do this. Any help is appreciated!! Thank you!
I found a solution to my own question... mostly. Here is the code I use to run the curl command at the end of the build process:
task uploadPro << {
logger.error("Uploading mapping.txt file to bugsnag")
def myCommand = "cmd /c curl https://upload.bugsnag.com -F proguard=#path\\to\mappingFile\\mapping.txt -F " +
"apiKey=111111111111111111111111 -F versionCode=" + versionCodeId + " -F " +
"appId=com.xxxx.yyy.zzz -F versionNumber=" + versionId
ProcessBuilder builder = new ProcessBuilder(myCommand.split(' '));
Process process = builder.start();
process.waitFor()
println process.err.text
println process.text
}
Then I use this to run it at the end of the build process:
gradle.buildFinished {
tasks.uploadPro.execute()
}
Cant be sure this is best practice but it works.
I would have liked to run the uploadPro task ONLY during a release buildType...but this proves to be difficult as well.
Related
I want to run a command line with Gradle that this command has an output.
I run this command in windows powershell:
./mybat.bat myArgs when I hit enter, it will print some digit, like this:
123456
I want to run this command with gradle and save this result(123456)
here is some code that I written in android build.gradle file:
task getSomeOutput(type: Exec) {
workingDir "${buildDir}/output"
commandLine 'powershell', './mybat.bat' , 'foo'//this is myArgs for example
}
this works and prints the value 123456, but I want to save it in a variable, how can I do that?
As you can see in the official doc HERE
This can be achieved with the following task
task executeCMD(type:Exec) {
workingDir '.'
commandLine 'mybat.bat', '>', 'log.txt'
doLast {
println "Executed!"
}
}
This will send the output of mybat.bat execution and set the results into a txt file called log .
the . is the directory where you have the script .
in my case its a project root directory .
the best approach I found is to add '/c' to commandLine arguments and use standardOutput, here some code that might help other people:
task getSomeOutput(type: Exec) {
workingDir "${buildDir}/output"
commandLine 'powershell', '/c', './mybat.bat' , 'foo'//this is myArgs for example
standardOutput = new ByteArrayOutputStream()
doLast {
def result = standardOutput.toString()
println "the result value is: $result"
}
}
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()
}
} }
As mentioned in Google Developers' article, it is now possible to recompress APK files using zopfli by running zipalign -z. In my case, a 200 KB reduction is observed on a 5.1 MB APK file.
Normally I build the APK using a custom shell script, by running gradle assembleRelease.
I want to run zipalign -z <the final apk> after the above command. However, zipalign is located in the build-tools/<build tools version> directory, which I can't locate it except by pulling out the <build tools version> from the build.gradle file and constructing the path manually.
Is it possible to run zipalign using the gradle command that automatically run the zipalign on the correct build-tools directory without me having to reconstuct the path?
For example a command such as gradle runBuildTools zipalign -z $FINAL_APK $FINAL_APK.out
The article that you linked to has been updated with the gradle task to add the zopfli compression to the end of the assembleRelease task.
//add zopfli to variants with release build type
android.applicationVariants.all { variant ->
if (variant.buildType.name == 'release') {
variant.outputs.each { output ->
output.assemble.doLast {
println "Zopflifying... it might take a while"
exec {
commandLine output.zipAlign.zipAlignExe,'-f','-z', '4', output.outputFile.absolutePath , output.outputFile.absolutePath.replaceAll('\\.apk$', '-zopfli.apk')
}
}
}
}
}
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.
How do I create an OBB file for my application using Gradle with the android plugin? As of now, I have to either zip or use the jobb tool to create my OBB file. If there were a means of creating the OBB file entirely through Gradle it would simplify my build process and my life.
MY current process involves creating a Gradle task that kicks of a shell script. Not totally desirable but it works. I am wondering however about zip support in Gradle.
task buildOBBOSX(type:Exec) {
workingDir '.'
//note: according to the docs, the version code used is that of the "first"
// apk with which the expansion is associated with
commandLine './buildOBB.sh'
//store the output instead of printing to the console:
standardOutput = new ByteArrayOutputStream()
ext.output = {
return standardOutput.toString()
}
}
Maybe this is the best solution? Possibly. If so, and nobody recommends better, I will add it as an answer.
Besides doing it the way you are trying to do it now, I found this:
Gradle:
all{currentFlavor ->
task ("create"+ currentFlavor.name.substring(0, 1).toUpperCase() + currentFlavor.name.substring(1)+"Obb", type:Zip){
archiveName = "main.${defaultConfig.versionCode}.${currentFlavor.applicationId}.obb"
ext.destDir = new File(buildDir, "obb/${currentFlavor.name}")
ext.destFile = new File(destDir, archiveName)
duplicatesStrategy DuplicatesStrategy.EXCLUDE
doFirst {
destDir.mkdirs()
}
description = "Creates expansion file for APK flavour ${currentFlavor.name}"
destinationDir = new File(buildDir, "obb/${currentFlavor.name}");
entryCompression = ZipEntryCompression.STORED
from "flavors/${currentFlavor.name}/obb", "obb"
tasks.createObb.dependsOn("create"+ currentFlavor.name.substring(0, 1).toUpperCase() + currentFlavor.name.substring(1)+"Obb")
}
}
Source: https://gitlab.labs.nic.cz/labs/tablexia/blob/devel/build.gradle#L154
Manually(you are doing this in your script):
Example, via command line:
jobb -d /temp/assets/ -o my-app-assets.obb -k secret-key -pn com.my.app.package -pv 11
Source: http://developer.android.com/tools/help/jobb.html
My Suggestions:
I'd recommend adding more to your task, similar to how this exec method works. This way, you can pass params or generate tasks using your packageName:
def createOBB(def assetsFolder, def obbFile, def secretKey, def packageName) {
def stdout = new ByteArrayOutputStream(), stderr = new ByteArrayOutputStream()
exec {
// jobb -d /temp/assets/ -o my-app-assets.obb -k secret-key -pn com.my.app.package -pv 11
commandLine 'jobb', '-d', assetsFolder, '-o', obbFile, '-k', secretKey, '-pn', packageName, '-pv', '11'
standardOutput = stdout
errorOutput = stderr
ignoreExitValue true // remove this if you want to crash if fail
}
}