This tutorial describes how to create a serverless mobile delivery pipeline in Google Cloud:
- First, it walks you through setting up a test Android application that you can build and distribute using Gradle commands on your local machine. These commands build the Android application package (APK) and upload it to Firebase App Distribution for distribution to beta testers.
- Next, to automate this process, you install the Android Builder for Cloud Build and set up a build trigger to automatically trigger build and distribution of the Android application with changes to its source code.
Objectives
- Create a build task that builds a signed APK.
- Create a build task that uses Firebase App Distribution to distribute new builds.
- Install the Android Builder with the required Android SDK dependencies.
- Create a build trigger in Google Cloud that uses the Android Builder to build the signed APK and distribute it using Firebase App Distribution.
Costs
This tutorial uses billable components of Google Cloud, including:
The base Android Builder image is about 1.9 GB. The Pricing Calculator estimates the cost of storage of 2 GB environment at around $.05 per month. Building the base Android Builder image takes about 11 minutes and costs $.03. Each additional build should take about 5 minutes and cost $.02. See Cloud Build pricing for more information.
Before you begin
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Cloud project. Learn how to check if billing is enabled on a project.
-
Enable the Compute Engine API.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Cloud project. Learn how to check if billing is enabled on a project.
-
Enable the Compute Engine API.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
- Make sure you have Gradle installed on your computer.
- Make sure you have Android Studio installed on your computer.
- Make sure that Git is installed on your computer.
This tutorial assumes the following:
- You're running macOS or Linux. Some of these procedures could be adapted to a Windows environment, but the tutorial does not provide complete instructions for that use case.
- You have some familiarity with Android development, Android Studio, and Gradle and Git.
Get the signed Android beta build working locally
In this section, you set up a test Android application in Android Studio. The application can be built and distributed using Gradle build tasks run in the terminal window of your computer.
Create a test Android application to build
In Android Studio, create a new Android Project that uses an empty activity.
The following screenshots show the steps in the wizard for performing this task.
From the terminal window on your computer, change to the directory where you created your test application:
cd ${HOME}/android-apps/TestAndroidBuild
In that directory, initialize a Git repository:
git init && git checkout -b develop
Edit the
.gitignore
file and add the names of files and extensions that Git should not push to your source code repository:cat >> .gitignore <<EOF google-services.json app-distro.json keystore.properties EOF
Commit the application to the repository:
git add -A git commit -m "empty application"
Configure the Google Cloud CLI to use your project. For
[PROJECT_NAME]
, use the project name that you selected or created.PROJECT=[PROJECT_NAME] gcloud config configurations create $PROJECT gcloud config config set project $PROJECT
Create a cloud source repository for your Android application:
gcloud source repos create android-application
Add the cloud source repository as a remote repository for your Android application:
git remote add google \ https://source.developers.google.com/p/${PROJECT}/r/android-application
Add Firebase to your application
Go to the Firebase Console:
Click Add Project.
Under Enter your project name, select the Google Cloud project that you created earlier:
.
Confirm the Firebase Blaze Billing Plan.
Select whether you want to enable Google Analytics. For this tutorial, you do not need to use analytics.
Wait for the Firebase project to be created, and then click Continue.
Follow the instructions at Add Firebase to your Android project to add Firebase to your Android application.
Ensure that your
google-services.json
file is moved to the following directory:{HOME}/android-apps/TestAndroidBuild
Follow the instructions at Get started with Firebase Crashlytics to add Firebase Crashlystics to your Android project.
Change directories to the app-level directory of your project:
cd {HOME}/android-apps/TestAndroidBuild/app
Create a Google Cloud service account with the Firebase admin role:
gcloud iam service-accounts create app-distro --display-name=app-distro APP_DISTRO_SA=$(gcloud iam service-accounts list --filter="displayName:app-distro" --format='value(email)') gcloud projects add-iam-policy-binding $PROJECT --role roles/firebase.admin --member serviceAccount:$APP_DISTRO_SA gcloud iam service-accounts keys create app-distro.json $APP_DISTRO_SA
Create the signing key and keystore
To distribute the pre-release Android application, you must sign the application
using a certificate that's stored in a Java keystore (.jks
) file.
In the terminal window, change to the parent directory of your application:
cd ${HOME}/AndroidStudioProjects/TestAndroidBuild
Create the Java keystore and key to sign the application, and create the
keystore.properties
file that stores the key alias, password, and relative path for the keystore file:JKS_PASSWORD=$(openssl rand -base64 12) keytool -genkey -noprompt -keystore ../signing/android.jks \ -alias android-key \ -dname "CN=example.com, OU=IT, O=Example, L=Sunnyvale, S=California, C=US" \ -storepass ${JKS_PASSWORD} \ -keypass ${JKS_PASSWORD} cat > ../signing/keystore.properties <<EOF storeFile=../signing/android.jks storePassword=${JKS_PASSWORD} keyPassword=${JKS_PASSWORD} keyAlias=android-key EOF
Encrypt the android secret files and add them to your source repository.
Enable the key management service:
gcloud services enable cloudkms.googleapis.com
Create a keyring to store your keys:
gcloud kms keyrings create my-app --location=global
Create a key to store your secrets:
gcloud kms keys create android-builder \ --location=global \ --keyring=my-app \ --purpose=encryption
Add the encrypt/decrypt role to the Cloud Build service account:
CLOUDBUILD_ACCOUNT=$(gcloud projects get-iam-policy $PROJECT \ --filter="(bindings.role:roles/cloudbuild.builds.builder)" \ --flatten="bindings[].members" \ --format="value(bindings.members[])" | tail -1) gcloud kms keys add-iam-policy-binding android-builder --location=global \ --keyring=my-app --member="${CLOUDBUILD_ACCOUNT} \ --role=roles/cloudkms.cryptoKeyEncrypterDecrypter
Encrypt the
keystore.properties
file:gcloud kms encrypt --plaintext-file=signing/keystore.properties \ --ciphertext-file=signing/keystore.properties.enc --location=global \ --keyring=my-app --key=android-builder
Add the signing files to your source repository:
git add signing git commit -m "encrypted signing information"
Encrypt the
google-services.json
file:gcloud kms encrypt --plaintext-file=app/google-services.json \ --ciphertext-file=app/google-services.json.enc --location=global \ --keyring=my-app --key=android-builder
Add the
google-services.json.enc
file to your source repository:git add app/google-services.json.enc git commit -m "encrypted application account"
Encrypt the
app-distro.json
file:gcloud kms encrypt --plaintext-file=app-distro.json \ --ciphertext-file=app-distro.json.enc \ --location=global \ --keyring=my-app --key=android-builder
Add the
app-distro.json.enc
file to your source repository:git add app-distro.json.enc git commit -m "encrypted service account"
Add Firebase App Distribution
- Follow the instructions at Distribute Android apps to testers using Gradle to add Firebase App Distribution to your application.
Create a Firebase distribution group
Go to the Firebase console:
Click the app you created for Firebase. The name is similar to the name of the Cloud project.
Click App Distribution.
Click Testers.
Click Add Testers.
Enter your email address.
Click Create a tester group.
Enter the name beta-testers.
Click Add testers.
Add your email address to the beta-testers group.
Update the build.gradle file to include the signing and Firebase distribution configurations
Update the
{HOME}/AndroidStudioProjects/TestAndroidBuild/build.gradle
file with lines in bold below:buildscript { ext.kotlin_version = '1.3.41' repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.5.0' classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version' classpath 'com.google.firebase:firebase-appdistribution-gradle:2.0.0' classpath 'com.google.gms:google-services:4.3.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } }
Add the following snippets to the
{HOME}/AndroidStudioProjects/TestAndroidBuild/app/build.gradle
file:android { // ... def debugKeystorePropertiesFile = rootProject.file("signing/keystore.properties") def keystoreProperties = new Properties() keystoreProperties.load(new FileInputStream(debugKeystorePropertiesFile)) //... android { //... signingConfigs { debug { keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] storeFile file(keystoreProperties['storeFile'].trim()) storePassword keystoreProperties['storePassword'] } } buildTypes { debug { firebaseAppDistribution { releaseNotesFile="release-notes.txt" groups="beta-testers" } } // ... packagingOptions { exclude "app-distro.json" } } }
Fix the test dependency in the Gradle file
Ensure the following line in bold is in your
${HOME}/AndroidStudioProjects/TestAndroidBuild/app/build.gradle
file:dependencies { //... androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' }
Build and distribute the app from your computer
In the terminal window, make sure you're at the parent directory for your test application:
{HOME}/AndroidStudioProjects/TestAndroidBuild
Build and distribute the app:
gradle assembleDebug appDistributionUploadDebug
An email is sent to the distribution group with a link that allows the user to install the application.
Save the changes to the build in your source repository
Commit your changes to the source repository:
git add app/build.gradle && git commit -m "Update build for distribution."
Create your Android build in Cloud Build
At this point, you have working Gradle build tasks that build and distribute your Android application. In this section, you set up Cloud Build to run these build tasks whenever there's a change to the master branch of the Cloud Source Repository.
Set the
PROJECT
environment variable:export PROJECT=$(gcloud config get-value project)
Create the storage bucket that the Android Builder will use to save its dependencies between builds:
gsutil mb gs://$PROJECT-cache-bucket
Create the storage bucket that the Android Builder will use to increment the Android Build number:
gsutil mb gs://$PROJECT-config-bucket
Create the storage bucket that the Android Builder will use to store artifacts:
gsutil mb gs://$PROJECT-artifact-bucket
Create the Android Builder
In a terminal window, clone the community builders repository to a directory outside of your Android application's directory:
git clone https://github.com/GoogleCloudPlatform/cloud-builders-community
The GitHub repository contains the community maintained builders.
Change to the directory that contains the
tar
builder:cd cloud-builders-community/tar
Add the
tar
builder to your project:gcloud builds submit --config=cloudbuild.yaml
Change to the directory that contains the Android Builder:
cd ../android
Create the Android Builder, passing the target SDK version as a substitution:
gcloud builds submit --config=cloudbuild.yaml \ --substitutions=_ANDROID_VERSION=28
Create the Android application build trigger
In this section, you create the Application build trigger that uses the Android Builder from the previous section to build and distribute the Android application.
In the terminal window, copy the example
cloudbuild.yaml
file from the Android builderexamples/
directory to your test Android application directory:cd ${HOME}/android-apps/TestAndroidBuild cp ${HOME}/cloud-builders-community/android/examples/build-test-deploy-firebase-distro.yaml \ ./cloudbuild.yaml
Add the new
cloudbuild.yaml
file to thedevelop
branch of your source repository:git add cloudbuild.yaml && git commit -m "Add android builder to project."
In the Google Cloud console, go to the Build Triggers page:
Click Create trigger.
Select the android-application repository.
For Name, enter android-application-build.
Under Configuration, select Cloud Build configuration file (yaml or json).
Under cloudbuild.yaml location, enter
/cloudbuild.yaml
.Click Add item. This lets you set variables for the build.
For each variable in the following table, enter the variable name (including the leading underscore), and then the value from your project.
Variable Value Purpose _CONFIG_BUCKET
The bucket used for storing the build number.gs://[PROJECT_NAME]-config-bucket
The URL of the bucket that will be used to store the build number. _CACHE_BUCKET
The bucket to use for caching build dependencies.gs://[PROJECT_NAME]-cache-bucket
Prevents Gradle from downloading the same dependencies from the internet with each build. _ARTIFACT_BUCKET
The Cloud Storage bucket used to store build artifacts.gs://[PROJECT_NAME]-artifact-bucket
The Android Builder stores intermediate and other artifacts here during the build. Click Create trigger.
Execute the application build trigger
You can now test that the application build trigger works and confirm that the application is distributed to your email.
In a terminal window, change directories to the top-level directory of your test Android application project:
cd ${HOME}/android-apps/TestAndroidBuild
To trigger the build, push to the master branch of the source code repository
git push google develop
In the Google Cloud console, go to the Cloud Build page.
Click the latest build in progress to see the build output for the application build.
Clean up
After you've finished this tutorial, you should clean up the resources that you created on Google Cloud so you won't be billed for them in the future. The following sections describe how to delete or turn off these resources.
Delete the project
The easiest way to eliminate billing is to delete the project that you created for the tutorial.
To delete the project:
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Delete image registries
Delete the image registries for your Android SDK image and Android application image.
- In the left navigation menu of the Google Cloud console, scroll to the Tools section and click Container Registry > Images.
Select all the images.
Click Delete.
Delete Cloud Storage buckets
Delete the Cloud Storage buckets that contain the Android signing information and the Fabric properties. In Cloud Shell, use these commands, substituting your values for the placeholders:
Set the
PROJECT
environment variable.export PROJECT=$(gcloud config get-value project)
Delete the storage buckets created for the build.
gsutil rm gs://$PROJECT-cache-bucket gsutil rm gs://$PROJECT-config-bucket gsutil rm gs://$PROJECT-artifact-bucket
Delete the build triggers
- Delete the base Android SDK build trigger.
- Delete the Android build trigger.
Delete the application from Firebase
Navigate to the Firebase console
Select the Firebase project you created for the tutorial. It should have a name similar to [PROJECT_NAME].
From the settings menu, select Project Settings.
Scroll to the bottom of the page and click
.
What's next
- Review Android documentation in more detail.
- Review Firebase documentation in more detail.