Générer, tester et déployer des applications Android

Azure DevOps Services

Vous pouvez configurer des pipelines pour générer, tester et déployer automatiquement des applications Android.

Prérequis

Vous devez disposer des éléments suivants :

Configurer le pipeline

Réalisez les tâches suivantes pour configurer un pipeline pour un échantillon d’application Android.

  1. Dupliquez (fork) le référentiel suivant dans votre compte GitHub pour obtenir le code d’une application Android simple.

    https://github.com/MicrosoftDocs/pipelines-android
    
  2. Connectez-vous à votre organisation Azure DevOps et accédez à votre projet.

  3. Sélectionnez Pipelines>Créer un pipeline ou Nouveau pipeline.

  4. Sélectionnez GitHub comme emplacement de votre code source.

    Screenshot showing list of repositories to select from.

    Vous serez peut-être redirigé vers GitHub pour vous connecter. Si c’est le cas, entrez vos informations d’identification GitHub.

  5. Sélectionnez le référentiel -android que vous avez précédemment dupliqué.

  6. Sélectionnez Approuver et installer sur l’écran qui suit.

    Azure Pipelines génère un fichier YAML pour votre pipeline.

  7. Sélectionnez Exécuter.

  8. Validez directement dans la branche primaire, puis choisissez Réexécuter.

  9. Attendez la fin de l’exécution.

Vous disposez d’un fichier YAML opérationnel (azure-pipelines.yml) dans votre référentiel qui est prêt à être personnalisé.

Conseil

Pour apporter des modifications au fichier YAML, sélectionnez le pipeline dans la page Pipelines, puis Modifiez le fichier azure-pipelines.yml.

Générer avec Gradle

Gradle est un outil de génération courant utilisé pour la génération de projets Android. Pour plus d’informations sur vos options, consultez la tâche Gradle.

# https://learn.microsoft.com/azure/devops/pipelines/ecosystems/android
pool:
  vmImage: 'macOS-latest'

steps:
- task: Gradle@2
  inputs:
    workingDirectory: ''
    gradleWrapperFile: 'gradlew'
    gradleOptions: '-Xmx3072m'
    publishJUnitResults: false
    testResultsFiles: '**/TEST-*.xml'
    tasks: 'assembleDebug'

Ajuster le chemin d’accès de la build

  • Ajustez la valeur workingDirectory si votre fichier gradlew n’est pas à la racine du référentiel. La valeur du répertoire doit être similaire à la racine du référentiel, comme AndroidApps/MyApp ou $(system.defaultWorkingDirectory)/AndroidApps/MyApp.

  • Ajustez la valeur gradleWrapperFile si votre fichier gradlew n’est pas à la racine du référentiel. La valeur du chemin d’accès du fichier doit être similaire à la racine du référentiel, par exemple AndroidApps/MyApp/gradlew ou $(system.defaultWorkingDirectory)/AndroidApps/MyApp/gradlew.

Ajuster les tâches Gradle

Ajustez la valeur des tâches pour la variante de build que vous préférez, par exemple assembleDebug ou assembleRelease. Pour plus d’informations, consultez la documentation de développement Google Android suivante :

Signer et aligner un package Android (APK)

Si votre build ne signe et ne zipalign pas déjà l’APK, ajoutez la tâche Signature Android au YAML. Un APK doit être signé pour s’exécuter sur un appareil au lieu d’un émulateur. Le zipaligning réduit la RAM consommée par l’application.

Important

Nous vous recommandons de stocker chacun des mots de passe suivants dans une variable secrète.

- task: AndroidSigning@2
  inputs:
    apkFiles: '**/*.apk'
    jarsign: true
    jarsignerKeystoreFile: 'pathToYourKeystoreFile'
    jarsignerKeystorePassword: '$(jarsignerKeystorePassword)'
    jarsignerKeystoreAlias: 'yourKeystoreAlias'
    jarsignerKeyPassword: '$(jarsignerKeyPassword)'
    zipalign: true

Test

Tester sur l’émulateur Android

Créez la tâche Bash et copiez/collez le code ci-dessous pour installer et exécuter l’émulateur. N’oubliez pas d’organiser les paramètres de l’émulateur pour qu’ils correspondent à votre environnement de test. L’émulateur démarre en tant que processus en arrière-plan et est disponible dans les tâches ultérieures.

#!/usr/bin/env bash

# Install AVD files
echo "y" | $ANDROID_HOME/cmdline-tools/latest/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"

Tester sur des appareils hébergés par Azure

Ajoutez la tâche Test App Center pour tester l’application dans un lab hébergé d’appareils iOS et Android. Une version d’évaluation gratuite d’App Center est requise, qui doit être convertie ultérieurement en version payante.

Inscrivez-vous auprès d’App Center d’abord.

# App Center test v1
# Test app packages with Visual Studio App Center.
- task: AppCenterTest@1
  inputs:
    appFile: # string. Alias: app. Required. Binary application file path. 
    artifactsDirectory: '$(Build.ArtifactStagingDirectory)/AppCenterTest' # string. Alias: artifactsDir. Required. Artifacts directory. Default: $(Build.ArtifactStagingDirectory)/AppCenterTest.
  # Prepare Tests
    #prepareTests: true # boolean. Alias: enablePrepare. Prepare tests. Default: true.
    frameworkOption: 'appium' # 'appium' | 'espresso' | 'calabash' | 'uitest' | 'xcuitest'. Alias: framework. Required when enablePrepare = true. Test framework. Default: appium.
    #appiumBuildDirectory: # string. Alias: appiumBuildDir. Required when enablePrepare = true && framework = appium. Build directory. 
    #espressoBuildDirectory: # string. Alias: espressoBuildDir. Optional. Use when enablePrepare = true && framework = espresso. Build directory. 
    #espressoTestApkFile: # string. Alias: espressoTestApkPath. Optional. Use when enablePrepare = true && framework = espresso. Test APK path. 
    #calabashProjectDirectory: # string. Alias: calabashProjectDir. Required when enablePrepare = true && framework = calabash. Project directory. 
    #calabashConfigFile: # string. Optional. Use when enablePrepare = true && framework = calabash. Cucumber config file. 
    #calabashProfile: # string. Optional. Use when enablePrepare = true && framework = calabash. Profile to run. 
    #calabashSkipConfigCheck: false # boolean. Optional. Use when enablePrepare = true && framework = calabash. Skip Configuration Check. Default: false.
    #uiTestBuildDirectory: # string. Alias: uitestBuildDir. Required when enablePrepare = true && framework = uitest. Build directory. 
    #uitestStorePath: # string. Optional. Use when enablePrepare = true && framework = uitest. Store file. 
    #uiTestStorePassword: # string. Alias: uitestStorePass. Optional. Use when enablePrepare = true && framework = uitest. Store password. 
    #uitestKeyAlias: # string. Optional. Use when enablePrepare = true && framework = uitest. Key alias. 
    #uiTestKeyPassword: # string. Alias: uitestKeyPass. Optional. Use when enablePrepare = true && framework = uitest. Key password. 
    #uiTestToolsDirectory: # string. Alias: uitestToolsDir. Optional. Use when enablePrepare = true && framework = uitest. Test tools directory. 
    #signInfo: # string. Optional. Use when framework = calabash || framework = uitest. Signing information. 
    #xcUITestBuildDirectory: # string. Alias: xcuitestBuildDir. Optional. Use when enablePrepare = true && framework = xcuitest. Build directory. 
    #xcUITestIpaFile: # string. Alias: xcuitestTestIpaPath. Optional. Use when enablePrepare = true && framework = xcuitest. Test IPA path. 
    #prepareOptions: # string. Alias: prepareOpts. Optional. Use when enablePrepare = true. Additional options. 
  # Run Tests
    #runTests: true # boolean. Alias: enableRun. Run tests. Default: true.
    credentialsOption: 'serviceEndpoint' # 'serviceEndpoint' | 'inputs'. Alias: credsType. Required when enableRun = true. Authentication method. Default: serviceEndpoint.
    #serverEndpoint: # string. Required when enableRun = true && credsType = serviceEndpoint. App Center service connection. 
    #username: # string. Required when enableRun = true && credsType = inputs. App Center username. 
    #password: # string. Required when enableRun = true && credsType = inputs. App Center password. 
    appSlug: # string. Required when enableRun = true. App slug. 
    devices: # string. Required when enableRun = true. Devices. 
    #series: 'master' # string. Optional. Use when enableRun = true. Test series. Default: master.
    #dsymDirectory: # string. Alias: dsymDir. Optional. Use when enableRun = true. dSYM directory. 
    localeOption: 'en_US' # 'da_DK' | 'nl_NL' | 'en_GB' | 'en_US' | 'fr_FR' | 'de_DE' | 'ja_JP' | 'ru_RU' | 'es_MX' | 'es_ES' | 'user'. Alias: locale. Required when enableRun = true. System language. Default: en_US.
    #userDefinedLocale: # string. Optional. Use when enableRun = true && locale = user. Other locale. 
    #loginOptions: # string. Alias: loginOpts. Optional. Use when enableRun = true && credsType = inputs. Additional options for login. 
    #runOptions: # string. Alias: runOpts. Optional. Use when enableRun = true. Additional options for run. 
    #skipWaitingForResults: false # boolean. Alias: async. Optional. Use when enableRun = true. Do not wait for test result. Default: false.
  # Advanced
    #cliFile: # string. Alias: cliLocationOverride. App Center CLI location. 
    #showDebugOutput: false # boolean. Alias: debug. Enable debug output. Default: false.

Conserver les artefacts avec l’enregistrement de build

Ajoutez les tâches Copier les fichiers et Publier des artefacts de build. Votre APK est stocké avec l’enregistrement de build ou le test, et est déployé dans des pipelines ultérieurs. Pour plus d’informations, consultez Artefacts.

- task: CopyFiles@2
  inputs:
    contents: '**/*.apk'
    targetFolder: '$(build.artifactStagingDirectory)'
- task: PublishBuildArtifacts@1

Déployer

Ajouter App Center

Ajoutez la tâche Distribuer App Center pour distribuer une application à un groupe de testeurs ou d’utilisateurs bêta, ou pour promouvoir l’application vers Intune ou Google Play. Un compte App Center gratuit est requis (aucun paiement n’est nécessaire).

# App Center distribute v3
# Distribute app builds to testers and users via Visual Studio App Center.
- task: AppCenterDistribute@3
  inputs:
    serverEndpoint: # string. Required. App Center service connection. 
    appSlug: # string. Required. App slug. 
    appFile: # string. Alias: app. Required. Binary file path. 
    #buildVersion: # string. Build version. 
    releaseNotesOption: 'input' # 'input' | 'file'. Alias: releaseNotesSelection. Required. Create release notes. Default: input.
    releaseNotesInput: # string. Required when releaseNotesSelection = input. Release notes. 
    #releaseNotesFile: # string. Required when releaseNotesSelection = file. Release notes file. 
    #isMandatory: false # boolean. Require users to update to this release. Default: false.
    destinationType: 'groups' # 'groups' | 'store'. Required. Release destination. Default: groups.
    #distributionGroupId: # string. Alias: destinationGroupIds. Optional. Use when destinationType = groups. Destination IDs. 
    #destinationStoreId: # string. Required when destinationType = store. Destination ID. 
    #isSilent: # boolean. Optional. Use when destinationType = groups. Do not notify testers. Release will still be available to install. 
  # Symbols
    #symbolsOption: 'Apple' # 'Apple' | 'Android' | 'UWP'. Alias: symbolsType. Symbols type. Default: Apple.
    #symbolsPath: # string. Optional. Use when symbolsType == AndroidNative || symbolsType = Windows. Symbols path. 
    #appxsymPath: # string. Optional. Use when symbolsType = UWP. Symbols path (*.appxsym). 
    #symbolsDsymFiles: # string. Alias: dsymPath. Optional. Use when symbolsType = Apple. dSYM path. 
    #symbolsMappingTxtFile: # string. Alias: mappingTxtPath. Optional. Use when symbolsType = Android. Mapping file. 
    #nativeLibrariesPath: # string. Optional. Use when symbolsType == Android. Native Library File Path. 
    #symbolsIncludeParentDirectory: # boolean. Alias: packParentFolder. Optional. Use when symbolsType = Apple. Include all items in parent folder.

Installer Google Play

Installez l’extension Google Play et utilisez les tâches suivantes pour automatiser l’interaction avec Google Play. Par défaut, ces tâches s’authentifient auprès de Google Play à l’aide d’une connexion de service que vous configurez.

Libérer

Ajoutez la tâche Google Play Libérer pour mettre en production une nouvelle version d’application Android dans le Google Play Store.

- task: GooglePlayRelease@4
  inputs:
    apkFile: '**/*.apk'
    serviceEndpoint: 'yourGooglePlayServiceConnectionName'
    track: 'internal'

Promouvoir

Ajoutez la tâche Google Play Promouvoir pour promouvoir une mise à jour d’application Android précédemment publiée d’une piste à une autre, comme alphabeta.

- task: GooglePlayPromote@3
  inputs:
    packageName: 'com.yourCompany.appPackageName'
    serviceEndpoint: 'yourGooglePlayServiceConnectionName'
    sourceTrack: 'internal'
    destinationTrack: 'alpha'

Augmentation du lancement

Ajoutez la tâche Google Play Augmentation du lancement pour augmenter le pourcentage de lancement d’une application qui a été précédemment mise en production sur la piste rollout.

- task: GooglePlayIncreaseRollout@2
  inputs:
    packageName: 'com.yourCompany.appPackageName'
    serviceEndpoint: 'yourGooglePlayServiceConnectionName'
    userFraction: '0.5' # 0.0 to 1.0 (0% to 100%)

Mise à jour de l'état

Ajoutez la tâche Google Play Mise à jour de l’état pour mettre à jour l’état de lancement de l’application qui a été précédemment mise en production sur la piste rollout.

  - task: GooglePlayStatusUpdate@2
    inputs:
      authType: ServiceEndpoint
      packageName: 'com.yourCompany.appPackageName'
      serviceEndpoint: 'yourGooglePlayServiceConnectionName'
      status: 'inProgress' # draft | inProgress | halted | completed

Questions fréquentes (FAQ)

Q : Comment faire pour créer des ensembles d’applications ?

R : Vous pouvez générer et signer votre ensemble d’applications avec un script inlined et un fichier sécurisé. Pour ce faire, téléchargez d’abord votre magasin de clés et stockez-le en tant que fichier sécurisé dans la bibliothèque. Ensuite, créez des variables pour keystore.password, key.alias et key.password dans un groupe de variables.

Ensuite, utilisez les tâches Télécharger un fichier sécurisé et Bash pour télécharger votre magasin de clés, puis générer et signer votre ensemble d’applications.

Dans ce fichier YAML, téléchargez un fichier sécurisé app.keystore et utilisez un script bash pour générer un ensemble d’applications. Ensuite, utilisez Copier les fichiers pour copier l’ensemble d'applications. Ensuite, créez et enregistrez un artefact avec Publier un artefact de build ou utilisez l’extension Google Play pour publier.

- task: DownloadSecureFile@1
  name: keyStore
  displayName: "Download keystore from secure files"
  inputs:
    secureFile: app.keystore

- task: Bash@3
  displayName: "Build and sign App Bundle"
  inputs:
    targetType: "inline"
    script: |
      msbuild -restore $(Build.SourcesDirectory)/myAndroidApp/*.csproj -t:SignAndroidPackage -p:AndroidPackageFormat=aab -p:Configuration=$(buildConfiguration) -p:AndroidKeyStore=True -p:AndroidSigningKeyStore=$(keyStore.secureFilePath) -p:AndroidSigningStorePass=$(keystore.password) -p:AndroidSigningKeyAlias=$(key.alias) -p:AndroidSigningKeyPass=$(key.password)

- task: CopyFiles@2
  displayName: 'Copy deliverables'
  inputs:
    SourceFolder: '$(Build.SourcesDirectory)/myAndroidApp/bin/$(buildConfiguration)'
    Contents: '*.aab'
    TargetFolder: 'drop'