Build and Release — Android
Prerequisites
Development Environment
| Tool | Version | Purpose |
|---|---|---|
| .NET SDK | 10.0.x | Build runtime |
| Android SDK | API 36 | Android platform ($env:LOCALAPPDATA\Android\Sdk\platforms;android-36) |
| Android Build Tools | 36.0.0 | APK compilation ($env:LOCALAPPDATA\Android\Sdk\build-tools;36.0.0) |
| Java JDK | 21 (exactly) | Android toolchain — JDK 25+ fails with XA0030 |
| Android Emulator | Latest | Testing |
JDK Setup (Windows)
# JDK 21 is bundled with Android SDK
$env:JAVA_HOME = "$env:LOCALAPPDATA\Android\Sdk\jdk-21"
# Verify
& "$env:JAVA_HOME\bin\java" -version
# openjdk version "21.0.x" ...
Do NOT use JDK 25+ — the Android SDK build tooling rejects it with error XA0030: Building with JDK version 25.x is not supported.
Visual Studio
For running from Visual Studio (VS2022+):
- Install workload: .NET Multi-platform App UI development (includes .NET for Android)
- Ensure Android SDK and JDK 21 are detected by VS
- Open
XBVault.sln, setXBVault.Androidas startup project, select emulator/device, F5
Project Structure
XBVault.sln ← Solution with all 4 projects
XBVault/XBVault.csproj ← Shared library (net10.0, Library)
XBVault.Desktop/XBVault.Desktop.csproj ← Desktop host (net10.0, WinExe/Exe)
XBVault.Android/XBVault.Android.csproj ← Android host (net10.0-android36.0, Exe)
tests/XBVault.Tests/XBVault.Tests.csproj ← xUnit tests (net10.0)
Why 3 Projects?
The Avalonia canonical pattern uses a shared library + platform hosts:
XBVault/is a pure Library (no OutputType, no RuntimeIdentifiers) — this is what makes the AndroidProjectReferencework without MSBuild outer-build hacksXBVault.Desktop/contains onlyProgram.cs(entry point) and referencesAvalonia.DesktopXBVault.Android/contains onlyMainActivity.csandAndroidApp.cs, referencesAvalonia.Android
Build Commands
Solution (everything)
$env:JAVA_HOME = "$env:LOCALAPPDATA\Android\Sdk\jdk-21"
rtk dotnet build XBVault.sln -c Debug
Desktop only
powershell -File build/build.ps1
# or
rtk dotnet build XBVault.Desktop/XBVault.Desktop.csproj -c Debug
Android only
$env:JAVA_HOME = "$env:LOCALAPPDATA\Android\Sdk\jdk-21"
powershell -File build/build-android.ps1
# or
rtk dotnet build XBVault.Android/XBVault.Android.csproj -c Debug
Run desktop
powershell -File build/run.ps1
Run Android (requires emulator or device)
$env:JAVA_HOME = "$env:LOCALAPPDATA\Android\Sdk\jdk-21"
powershell -File build/run-android.ps1
Release builds
# Desktop (Windows x64)
powershell -File build/build-release.ps1 -Version 1.4.0 -Arch x64
# Desktop (Linux/macOS)
bash build/build-release.sh 1.4.0 x64
# Android (arm64)
$env:JAVA_HOME = "$env:LOCALAPPDATA\Android\Sdk\jdk-21"
powershell -File build/build-release-android.ps1 -Version 1.4.0
Tests
rtk dotnet test tests/XBVault.Tests/XBVault.Tests.csproj -c Release
# 240 tests, all pass
CI/CD Pipeline
GitHub Actions (.github/workflows/build.yml)
| Job | Trigger | Runner | What it does |
|---|---|---|---|
build |
push/PR to main | windows-latest + ubuntu-latest | dotnet build XBVault.Desktop |
build-android |
push/PR to main | windows-latest | dotnet build XBVault.Android (JDK 21 + Android SDK) |
test |
push/PR to main | windows-latest + ubuntu-latest | dotnet test |
release |
tag v* |
matrix | win-x64, win-arm64, linux-x64, osx-x64, osx-arm64, android-arm64 |
publish |
tag v* |
ubuntu-latest | GitHub Release with all ZIPs + checksums |
Release Matrix
| Platform | RID | Script | Output |
|---|---|---|---|
| Windows x64 | win-x64 | build-release.ps1 |
XBVault-v{V}-win-x64.zip + optional installer |
| Windows ARM64 | win-arm64 | build-release.ps1 -Arch arm64 |
XBVault-v{V}-win-arm64.zip |
| Linux x64 | linux-x64 | build-release.sh |
XBVault-v{V}-linux-x64.zip |
| Linux ARM64 | linux-arm64 | build-release.sh |
XBVault-v{V}-linux-arm64.zip |
| macOS x64 | osx-x64 | build-release.sh |
XBVault-v{V}-osx-x64.zip |
| macOS ARM64 | osx-arm64 | build-release.sh |
XBVault-v{V}-osx-arm64.zip |
| Android ARM64 | android-arm64 | build-release-android.ps1 |
XBVault-v{V}-android-arm64.zip |
Android Manifest
XBVault.Android/AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:label="XBVault"
android:allowBackup="false"
android:supportsRtl="true"
android:theme="@style/MainTheme" />
</manifest>
Permissions: INTERNET + ACCESS_NETWORK_STATE (required for Xbox HTTP/SSH).
Android Resources
XBVault.Android/Resources/values/styles.xml:
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="MainTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>
A values-v31 variant provides Material You splash support.
Troubleshooting
“Building with JDK version 25.x is not supported”
Use JDK 21: set JAVA_HOME=%LOCALAPPDATA%\Android\Sdk\jdk-21
“minSdkVersion 21 cannot be smaller than version 23”
SupportedOSPlatformVersion in XBVault.Android.csproj must be 23 (required by androidx.lifecycle.runtime dependency from Avalonia.Android).
“Ambiguous project name ‘XBVault’”
The shared library and desktop host must not both have AssemblyName=XBVault. Currently, neither sets AssemblyName explicitly — defaults to XBVault (shared) and XBVault.Desktop (host).
“resource style/MainTheme not found”
Ensure XBVault.Android/Resources/values/styles.xml exists with a MainTheme style definition.
Android build hangs / OOM
Single RID (android-arm64) avoids MSBuild outer-multi-RID build issues. Do not add more RIDs to RuntimeIdentifiers in the Android csproj without understanding the outer-build propagation problem.
Output Artifacts
| Artifact | Extension | Use Case |
|---|---|---|
| Debug APK | .apk |
Development and testing |
| Release APK | .apk |
Sideload distribution |
| AAB | .aab |
Google Play Store |
File Naming Convention
XBVault-v{Version}-android-arm64.zip