Skip to content

Instantly share code, notes, and snippets.

@biklas7
Last active March 21, 2024 20:28
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save biklas7/8c381970fdfbb0de2542b7a8e4a94989 to your computer and use it in GitHub Desktop.
Save biklas7/8c381970fdfbb0de2542b7a8e4a94989 to your computer and use it in GitHub Desktop.
A Gradle task that generates and publish an Android .apk file to an S3 bucket.

Publish Android .apk file to an S3 bucket

Setup your S3 variables

You can either set up the S3 variables for all projects or per individual project if you prefer. In this example, I will do it for all projects. Just open the build.gradle file and add the following code.

allprojects {
    project.ext.AWS_S3_BUCKET = "YOUR BUCKET NAME"
    project.ext.AWS_S3_KEY_ID = "YOUR BUCKED SECRET ID"
    project.ext.AWS_S3_KEY_SECRET = "YOUR BUCKED SECRET KEY"
    project.ext.AWS_S3_APK_TARGET_FOLDER = "YOUR S3 TARGET FOLDER"
}

If possible, I highly recommend that you save the Access Key and Secret Key as environment variables so they won't end up in your code repository.

Add the publish task to your project

Download the publishApkToS3.gradle file and put it in your app folder.

Then, in the build.gradle of each application you want to publish add the following:

apply from: 'publishApkToS3.gradle'

Finally, you just have to execute the task using the command publish{flavor-name}ToS3.

PS: This script uses CURL, so make sure you have it installed in your machine.

import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import java.text.SimpleDateFormat
android.applicationVariants.all { variant ->
task("publish${variant.name.capitalize()}ToS3", dependsOn: "assemble${variant.name.capitalize()}").doLast {
if (!project.hasProperty('AWS_S3_BUCKET')) {
throw new Exception("Please set AWS_S3_BUCKET propertiy.")
}
if (!project.hasProperty('AWS_S3_KEY_ID')) {
throw new Exception("Please set AWS_S3_KEY_ID property.")
}
if (!project.hasProperty('AWS_S3_KEY_SECRET')) {
throw new Exception("Please set AWS_S3_KEY_SECRET property.")
}
def bucket = project.AWS_S3_BUCKET
def keyId = project.AWS_S3_KEY_ID
def keySecret = project.AWS_S3_KEY_SECRET
def prefix = project.hasProperty('AWS_S3_APK_TARGET_FOLDER') ? project.AWS_S3_APK_TARGET_FOLDER + "/" : ""
def targetPath = prefix + "${variant.flavorName.capitalize()}/" + "${variant.name.capitalize()}-${variant.versionName}.apk"
def apkFile = variant.outputs[0].outputFile
def contentType = "application/vnd.android.package-archive"
def date = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss ZZZZ").format(new Date())
def resource = "/${bucket}/${targetPath}"
def data = "PUT\n\n${contentType}\n${date}\n${resource}"
def signingKey = new SecretKeySpec(keySecret.getBytes(), "HmacSHA1")
def mac = Mac.getInstance("HmacSHA1")
mac.init(signingKey)
def sig = mac.doFinal(data.getBytes()).encodeBase64()
exec {
executable 'curl'
args '-k', '-X', 'PUT',
'-T', apkFile.getAbsolutePath(),
'-H', 'Date: ' + date,
'-H', 'Authorization: AWS ' + keyId + ':' + sig,
'-H', 'Content-Type: ' + contentType,
'-H', "Host: ${bucket}.s3.amazonaws.com",
'https://' + bucket + '.s3.amazonaws.com/' + targetPath
}
}
}
@iamanvesh
Copy link

@biklas7 this is not working anymore. I'm facing the following issue

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>InvalidRequest</Code>
  <Message>The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.</Message> . 
  ...
</Error>

Any idea how to fix this issue?

@biklas7
Copy link
Author

biklas7 commented Nov 18, 2019

@pmjsankar
Copy link

:~/Documents/Backup/APItestapp$ publishDebugToS3
publishDebugToS3: command not found

@biklas7 I'm getting 'command not found' error. Can you please help?
I have only the default debug & release variants.

image

@biklas7
Copy link
Author

biklas7 commented Mar 28, 2022

@pmjsankar did you apply the plugin?

apply from: 'publishApkToS3.gradle'

@pmjsankar
Copy link

Yes. You can see that in the above image, line number 5.

@biklas7
Copy link
Author

biklas7 commented Mar 28, 2022

@pmjsankar is the publishApkToS3.gradle file in the app folder?

@pmjsankar
Copy link

@biklas7 Yes.

@pmjsankar
Copy link

@biklas7 Anyways I managed to upload the APK by using the below command:
./gradlew tasks publishReleaseToS3

Thanks for your support.

@biklas7
Copy link
Author

biklas7 commented Mar 28, 2022

@pmjsankar ah yes you run the command using gradlew. Didn't remember to mention that, but glad it works now 💪

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment