Logo

dev-resources.site

for different kinds of informations.

How to build a MAUI app in Azure Devops

Published at
10/29/2024
Categories
maui
azuredevop
testflight
googleplay
Author
stfnilsson
Author
10 person written this
stfnilsson
open
How to build a MAUI app in Azure Devops

- and how to publish it to Test Flight and Google Play Console

You have created a .NET MAUI app but you have been building it on your laptop and now want to know how to send it to Testers or to the Store.

Environment

This blog post is covering building via Azure Devops but there are many other options, like Github.

In Azure Devops you can setup your own build agent by following this guide: https://learn.microsoft.com/sv-se/azure/devops/pipelines/agents/osx-agent?view=azure-devops

You can also use a hosted agent. Here are some different alternatives: https://learn.microsoft.com/sv-se/azure/devops/pipelines/agents/hosted?view=azure-devops&tabs=yaml#software

For building a Maui app for iOS you need a Mac. In this build pipeline 'macos-14' is used.

pool:
  vmImage: 'macos-14'
Enter fullscreen mode Exit fullscreen mode

Global settings

To share settings between build pipelines or to just abstract away the settings you can use Library in Azure Devops.

In this example the variable group "Svetto" is used.

Image description

You define the variable group in your build pipeline like this:

variables:
  - group: Svetto
Enter fullscreen mode Exit fullscreen mode

This is all the setting which is used to build both for iOS and Android, the name of the files is also specified as variables.

For signing the Android app:

  • AndroidKeyStoreAlias
  • AndroidKeyStoreFile
  • AndroidKeyStorePassword

For signing the iOS app:

  • AppleCertificate
  • AppleSigningIdentity
  • iOSCertPassword
  • ProvisioningProfile

The version (major.minor)

  • ApplicationDisplayVersion

Image description

The files needed to sign the app are:

  • .p12 which is the Apple Certificate

  • .mobileprovision which is the Apple Provision Profile

  • .keystore which is used to sign the Android app

Image description

Version number

A version number contains of three digits {major.minor.build}.

The major and the minor are specified in the project file:
<ApplicationDisplayVersion>2.0</ApplicationDisplayVersion>

To make the build number unique build/runner in devops is often used but it's also possible to use the date like this:

<ApplicationVersion>$([System.DateTime]::Now.ToString('yyyyMMddHH'))</ApplicationVersion>

Preparing

Select Xcode version

If you want to use a specific version of Xcode you can use this inline script, here it's specified that Xcode 16 should be used.

- task: CmdLine@2
  displayName: 'Selects a specific version of Xcode'
  inputs:
    script: 'sudo xcode-select -switch /Applications/Xcode_16.app/Contents/Developer'
Enter fullscreen mode Exit fullscreen mode

Install latest .net MAUI

- task: CmdLine@2
  displayName: 'Install Latest .NET MAUI Workload '
  inputs:
    script: 'dotnet workload install maui'
Enter fullscreen mode Exit fullscreen mode

You can adjust the --source to target specific versions of .NET MAUI workloads, and you can learn more about changing sources in the .NET MAUI Wiki (https://github.com/dotnet/maui/wiki/#install-net-6-with-net-maui).

Install apple certificate and provision profile

For iOS, you need a signing certificate and a provisioning profile. This guide walks you through how to obtain these files:(https://learn.microsoft.com/sv-se/azure/devops/pipelines/apps/mobile/app-signing?view=azure-devops&tabs=yaml#apple)

- task: InstallAppleCertificate@2
  inputs:
    certSecureFile: '$(AppleCertificate)'
    certPwd: '$(iOSCertPassword)'
    keychain: 'temp'
Enter fullscreen mode Exit fullscreen mode
- task: InstallAppleProvisioningProfile@1
  displayName: 'Install app store provisioning profile'
  inputs:
    provisioningProfileLocation: 'secureFiles'
    provProfileSecureFile: '$(ProvisioningProfile)'
Enter fullscreen mode Exit fullscreen mode

Add Android keystore key

For Android, you need keystore file and value of keystore password and keystore alias. This guide walks you through how to obtain these files: (https://learn.microsoft.com/sv-se/azure/devops/pipelines/apps/mobile/app-signing?view=azure-devops&tabs=yaml#sign-your-android-app)

- task: DownloadSecureFile@1
  name: keystore
  inputs:
    secureFile: '$(AndroidKeyStoreFile)'
Enter fullscreen mode Exit fullscreen mode

Building

Build iOS

In .NET 8, the dotnet publish command defaults to the Release configuration. Therefore, the build configuration can be omitted from the command line. In addition, the dotnet publish command also defaults to the ios-arm64 RuntimeIdentifier. The RuntimeIdentifier can also be omitted from the command line.

.NET MAUI apps produce executables for each Target Framework—these are native app packages with all dependencies/resources bundled in.

- task: DotNetCoreCLI@2
  displayName: 'dotnet publish iOS'
  inputs:
    command: 'publish'
    publishWebProjects: false
    projects: '**/Svetto.sln'
    arguments: '-f net8.0-ios -c Release -p:ApplicationDisplayVersion=$(ApplicationDisplayVersion) -p:ArchiveOnBuild=true -p:EnableAssemblyILStripping=false -p:RuntimeIdentifier=ios-arm64'
    zipAfterPublish: false
Enter fullscreen mode Exit fullscreen mode

Copy ipa to stage folder

- task: CopyFiles@2
  displayName: 'Copy iOS artifact'
  inputs:
    Contents: '**/*.ipa'
    TargetFolder: '$(Build.ArtifactStagingDirectory)'
    CleanTargetFolder: true
    OverWrite: true
    flattenFolders: true
Enter fullscreen mode Exit fullscreen mode

Build Android

- task: DotNetCoreCLI@2
  displayName: 'dotnet publish android'
  inputs:
    command: 'publish'
    publishWebProjects: false
    projects: '**/Svetto.sln'
    arguments: '-f net8.0-android -c Release -p:ApplicationDisplayVersion=$(ApplicationDisplayVersion) -p:AndroidKeyStore=true -p:AndroidSigningKeyStore=$(keystore.secureFilePath) -p:AndroidSigningKeyPass=$(AndroidKeyStorePassword) -p:AndroidSigningStorePass=$(AndroidKeyStorePassword) -p:AndroidSigningKeyAlias=$(AndroidKeyStoreAlias)'
    zipAfterPublish: false
Enter fullscreen mode Exit fullscreen mode

Copy aab to stage folder

- task: CopyFiles@2
  displayName: 'Copy android artifact'
  inputs:
    Contents: |
      **/*Signed.aab
    TargetFolder: '$(Build.ArtifactStagingDirectory)'
    OverWrite: true
    flattenFolders: true
Enter fullscreen mode Exit fullscreen mode

Publishing

Publish staged files, connect them to the build task

If you want to attach the ipa/abb to the build task you can use this task to publish the artifact to the task, as a zipfile called 'drop'.

- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: drop'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)'
Enter fullscreen mode Exit fullscreen mode

Publish to Apple TestFlight

Prerequisites

  • In order to automate the release of app updates to the App Store, you need to have manually released at least one version of the app beforehand.
  • The tasks install and use fastlane tools. fastlane requires Ruby 2.0.0 or above and recommends having the latest Xcode command line tools installed on the MacOS computer.

Read more about the extension here:
https://github.com/microsoft/app-store-vsts-extension/tree/master

- task: AppStoreRelease@1
  displayName: 'Publish to Test Flight'
  inputs:
    serviceEndpoint: 'AppleTestFlight'
    releaseTrack: 'TestFlight'
    appIdentifier: 'xxxxxxxx'
    appType: 'iOS'
    appSpecificId: 'xxxxxxxx'
    shouldSkipWaitingForProcessing: true
    isTwoFactorAuth: true
Enter fullscreen mode Exit fullscreen mode

Publish to Google Play Console

To publish a .NET MAUI Android app for Google Play distribution requires that your app package format is AAB, which is the default package format for release builds. To verify that your app's package format is set correctly:

In Visual Studio's Solution Explorer right-click on your .NET MAUI app project and select Properties. Then, navigate to the Android > Options tab and ensure that the value of the Release field is set to bundle:

Image description

The first time an AAB is submitted to Google Play, it must be manually uploaded through the Google Play Console. This enables Google Play to match the signature of the key on all future bundles to the original key used for the first version of the app. In order to upload the app through the Google Play Console, it must first be built and signed in Visual Studio.

- task: GooglePlayRelease@4
  inputs:
    serviceConnection: 'GooglePlayConsole'
    applicationId: 'xxxxxxxx'
    action: 'SingleBundle'
    bundleFile: '$(build.artifactstagingdirectory)/*.aab'
    track: 'internal'
    isDraftRelease: true
Enter fullscreen mode Exit fullscreen mode

Conclusion

Next year AppCenter will be deprecated so MAUI developers need to find other ways to share their app to testers and users. Publishing them to the test stores (TestFlight/Google Play Console) is the recommended way.

I hope this guide will help you. Even if it doesn't cover all details about certificates, configuration and setup in the stores.

Good luck!

maui Article's
30 articles in total
Favicon
Sneak Peek at 2024 Volume 4: .NET MAUI
Favicon
Open Source Tools for .NET MAUI
Favicon
How to Build a .NET MAUI Barcode Scanner Using IronBarcode
Favicon
Adding Platform-Specific Code to a .NET MAUI Project
Favicon
How to build a MAUI app in Azure Devops
Favicon
Create a .NET MAUI Bubble Chart to Visualize Market Cap Distribution by Country – GDP and Company Analysis
Favicon
Develop .NET MAUI Apps Using VS Code Without Traditional IDEs
Favicon
Embracing the Blazor Hybrid Approach in .NET MAUI
Favicon
The Luhn's algorithm in practice
Favicon
Chart of the Week: Visualizing Top 25 Largest Countries Using .NET MAUI Column Chart
Favicon
Free online Maui discussion 09/12/24 10:00am CST
Favicon
Design a Timer App using .NET MAUI Radial Gauge and Timer Picker
Favicon
Making Payments Easy: Using .NET MAUI Radio Button for Payment Apps and Digital Wallets
Favicon
Chart of the Week: Create .NET MAUI Multi-Category Bar Charts to Compare the Use of Generative AI for Creating Media vs....
Favicon
Introducing the New .NET MAUI Digital Gauge Control
Favicon
Mastering Shopping: Enhancing Your Product Search with the .NET MAUI CheckBox
Favicon
Introducing the 12th Set of New .NET MAUI Controls and Features
Favicon
Microsoft Build 2024: The Syncfusion Experience
Favicon
What’s New in .NET MAUI Charts: 2024 Volume 2
Favicon
Enhance PDF Viewing and Editing with the New Built-in Toolbar in .NET MAUI PDF Viewer
Favicon
Building a .NET TWAIN Document Scanner Application for Windows and macOS using MAUI
Favicon
Chart of the Week: Creating the .NET MAUI Radial Bar to Visualize Apple’s Revenue Breakdown
Favicon
Building .NET MAUI Barcode Scanner with Visual Studio Code on macOS
Favicon
Easily Export .NET MAUI DataGrid to Specific PDF Page
Favicon
Chart of the Week: Creating a .NET MAUI Doughnut Chart to Visualize the World’s Biggest Oil Producers
Favicon
Microsoft Build 2024: Key Takeaways and Insights
Favicon
Chart of the Week: Creating the .NET MAUI Scatter Chart to Visualize Different Sports Ball Sizes and Weights
Favicon
Syncfusion Essential Studio 2024 Volume 2 Is Here!
Favicon
OCR in .NET MAUI
Favicon
Sneak Peek at 2024 Volume 2: .NET MAUI

Featured ones: