Build, test, and deploy Android apps
This guidance explains how to automatically build, test, and deploy Android apps.
Get started
Follow these instructions to set up a pipeline for a sample Android app.
The code in the following repository is a simple Android app. To get started, fork this repo to your GitHub account.
https://github.com/MicrosoftDocs/pipelines-android
Sign in to your Azure DevOps organization and navigate to your project.
In your project, navigate to the Pipelines page. Then choose the action to create a new pipeline.
Walk through the steps of the wizard by first selecting GitHub as the location of your source code.
You might be redirected to GitHub to sign in. If so, enter your GitHub credentials.
When the list of repositories appears, select your Java sample repository.
Azure Pipelines will analyze the code in your repository and recommend starter templates for your pipeline. Select the
Android
template.Azure Pipelines will generate a YAML file for your pipeline. Select Save and run, then select Commit directly to the main branch, and then choose Save and run again.
A new run is started. Wait for the run to finish.
When you're done, you'll have a working YAML file (azure-pipelines.yml
) in your repository that's ready for you to customize.
Tip
To make changes to the YAML file as described in this topic, select the pipeline in the Pipelines page, and then Edit the azure-pipelines.yml
file.
Gradle
Gradle is a common build tool used for building Android projects. See the Gradle task for more about these options.
# https://docs.microsoft.com/azure/devops/pipelines/ecosystems/android
pool:
vmImage: 'macOS-10.14'
steps:
- task: Gradle@2
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: false
testResultsFiles: '**/TEST-*.xml'
tasks: 'assembleDebug'
Adjust the build path
Adjust the workingDirectory value if your gradlew
file isn't in the root of the repository.
The directory value should be relative to the root of the repository,
such as AndroidApps/MyApp
or $(system.defaultWorkingDirectory)/AndroidApps/MyApp
.
Adjust the gradleWrapperFile value if your gradlew
file isn't in the root of the repository.
The file path value should be relative to the root of the repository,
such as AndroidApps/MyApp/gradlew
or $(system.defaultWorkingDirectory)/AndroidApps/MyApp/gradlew
.
Adjust Gradle tasks
Adjust the tasks value for the build variant you prefer, such as assembleDebug
or assembleRelease
.
For details, see Google's Android development documentation:
Build a debug APK and
Configure build variants.
Sign and align an Android APK
If your build does not already sign and zipalign the APK, add the Android Signing task to the YAML. An APK must be signed to run on a device instead of an emulator. Zipaligning reduces the RAM consumed by the app.
Important: We recommend storing each of the following passwords in a secret variable.
- task: AndroidSigning@2
inputs:
apkFiles: '**/*.apk'
jarsign: true
jarsignerKeystoreFile: 'pathToYourKeystoreFile'
jarsignerKeystorePassword: '$(jarsignerKeystorePassword)'
jarsignerKeystoreAlias: 'yourKeystoreAlias'
jarsignerKeyPassword: '$(jarsignerKeyPassword)'
zipalign: true
Test on the Android Emulator
Note: The Android Emulator is currently available only on the Hosted macOS agent.
Create the Bash Task and copy paste the code below in order to install and run the emulator. Don't forget to arrange the emulator parameters to fit your testing environment. The emulator will be started as a background process and available in subsequent tasks.
#!/usr/bin/env bash
# Install AVD files
echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;android-27;google_apis;x86'
# Create emulator
echo "no" | $ANDROID_HOME/tools/bin/avdmanager create avd -n xamarin_android_emulator -k 'system-images;android-27;google_apis;x86' --force
$ANDROID_HOME/emulator/emulator -list-avds
echo "Starting emulator"
# Start emulator in background
nohup $ANDROID_HOME/emulator/emulator -avd xamarin_android_emulator -no-snapshot > /dev/null 2>&1 &
$ANDROID_HOME/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 1; done; input keyevent 82'
$ANDROID_HOME/platform-tools/adb devices
echo "Emulator started"
Test on Azure-hosted devices
Add the App Center Test task to test the app in a hosted lab of iOS and Android devices. An App Center free trial is required which must later be converted to paid.
Sign up with App Center first.
# App Center test
# Test app packages with Visual Studio App Center
- task: AppCenterTest@1
inputs:
appFile:
#artifactsDirectory: '$(Build.ArtifactStagingDirectory)/AppCenterTest'
#prepareTests: true # Optional
#frameworkOption: 'appium' # Required when prepareTests == True# Options: appium, espresso, calabash, uitest, xcuitest
#appiumBuildDirectory: # Required when prepareTests == True && Framework == Appium
#espressoBuildDirectory: # Optional
#espressoTestApkFile: # Optional
#calabashProjectDirectory: # Required when prepareTests == True && Framework == Calabash
#calabashConfigFile: # Optional
#calabashProfile: # Optional
#calabashSkipConfigCheck: # Optional
#uiTestBuildDirectory: # Required when prepareTests == True && Framework == Uitest
#uitestStorePath: # Optional
#uiTestStorePassword: # Optional
#uitestKeyAlias: # Optional
#uiTestKeyPassword: # Optional
#uiTestToolsDirectory: # Optional
#signInfo: # Optional
#xcUITestBuildDirectory: # Optional
#xcUITestIpaFile: # Optional
#prepareOptions: # Optional
#runTests: true # Optional
#credentialsOption: 'serviceEndpoint' # Required when runTests == True# Options: serviceEndpoint, inputs
#serverEndpoint: # Required when runTests == True && CredsType == ServiceEndpoint
#username: # Required when runTests == True && CredsType == Inputs
#password: # Required when runTests == True && CredsType == Inputs
#appSlug: # Required when runTests == True
#devices: # Required when runTests == True
#series: 'master' # Optional
#dsymDirectory: # Optional
#localeOption: 'en_US' # Required when runTests == True# Options: da_DK, nl_NL, en_GB, en_US, fr_FR, de_DE, ja_JP, ru_RU, es_MX, es_ES, user
#userDefinedLocale: # Optional
#loginOptions: # Optional
#runOptions: # Optional
#skipWaitingForResults: # Optional
#cliFile: # Optional
#showDebugOutput: # Optional
Retain artifacts with the build record
Add the Copy Files and Publish Build Artifacts tasks to store your APK with the build record or test and deploy it in subsequent pipelines. See Artifacts.
- task: CopyFiles@2
inputs:
contents: '**/*.apk'
targetFolder: '$(build.artifactStagingDirectory)'
- task: PublishBuildArtifacts@1
Deploy
App Center
Add the App Center Distribute task to distribute an app to a group of testers or beta users, or promote the app to Intune or Google Play. A free App Center account is required (no payment is necessary).
# App Center distribute
# Distribute app builds to testers and users via Visual Studio App Center
- task: AppCenterDistribute@1
inputs:
serverEndpoint:
appSlug:
appFile:
#symbolsOption: 'Apple' # Optional. Options: apple
#symbolsPath: # Optional
#symbolsPdbFiles: '**/*.pdb' # Optional
#symbolsDsymFiles: # Optional
#symbolsMappingTxtFile: # Optional
#symbolsIncludeParentDirectory: # Optional
#releaseNotesOption: 'input' # Options: input, file
#releaseNotesInput: # Required when releaseNotesOption == Input
#releaseNotesFile: # Required when releaseNotesOption == File
#isMandatory: false # Optional
#distributionGroupId: # Optional
Google Play
Install the Google Play extension and use the following tasks to automate interaction with Google Play. By default, these tasks authenticate to Google Play using a service connection that you configure.
Release
Add the Google Play Release task to release a new Android app version to the Google Play store.
- task: GooglePlayRelease@2
inputs:
apkFile: '**/*.apk'
serviceEndpoint: 'yourGooglePlayServiceConnectionName'
track: 'internal'
Promote
Add the Google Play Promote
task to promote a previously-released Android app update from one track to another, such as alpha
→ beta
.
- task: GooglePlayPromote@2
inputs:
packageName: 'com.yourCompany.appPackageName'
serviceEndpoint: 'yourGooglePlayServiceConnectionName'
sourceTrack: 'internal'
destinationTrack: 'alpha'
Increase rollout
Add the Google Play Increase Rollout
task to increase the rollout percentage of an app that was previously released to the rollout
track.
- task: GooglePlayIncreaseRollout@1
inputs:
packageName: 'com.yourCompany.appPackageName'
serviceEndpoint: 'yourGooglePlayServiceConnectionName'
userFraction: '0.5' # 0.0 to 1.0 (0% to 100%)
Related extensions
- Codified Security (Codified Security)
- Google Play (Microsoft)
- Mobile App Tasks for iOS and Android (James Montemagno)
- Mobile Testing Lab (Perfecto Mobile)
- React Native (Microsoft)