Repository navigation
[Xamarin.Installer.Build.Tasks] Use Android CLI to install SDK packages - #13513
Merged
Merged
Conversation
The `InstallAndroidDependencies` target used our own copy of the Android SDK manager (`Xamarin.Installer.AndroidSDK` and `Xamarin.Installer.Common`) to read the Xamarin manifest, download archives, and extract them. This is a lot of code to maintain, and Google now ships the Android CLI, which does the same job. Remove both projects. `InstallAndroidDependencies` now downloads a pinned Android CLI from dl.google.com, checks its SHA-256 against hashes in `Xamarin.Installer.Common.targets`, caches it under `LocalApplicationData/Android/android-cli/<version>`, and runs `android sdk install`. After the CLI exits, the task checks the SDK again, because the CLI can exit with 0 for an unknown package. JDK installation stays. A simplified `JavaDependencyInstaller` is copied from the removed project, and it now downloads from aka.ms/download-jdk. OpenJDK signature verification (XA5305) does not change. The Android CLI accepts the Android SDK licenses without a prompt, so `$(AcceptAndroidSDKLicenses)` is the only consent. The error message now links to the Android SDK License Agreement. `$(AndroidManifestType)`, `$(AndroidManifestSource)`, and `$(_AndroidIgnoreSdkArchiveChecksumErrors)` are removed. The docs list them as removed in .NET 12. Google does not ship a Windows Arm64 build of the Android CLI, so the task reports an unsupported platform error there. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Clean SDK packaging still references an INIFileParser.dll dependency that is no longer produced, while new failures lack coded diagnostics and Windows cancellation can still replace the existing JDK.
3 open issues
What changed in this PR
This PR replaces the legacy Xamarin SDK installer with Google’s Android CLI, reducing the SDK-management code maintained by .NET for Android while retaining JDK installation and signature verification.
Changes:
- Configures a pinned, SHA-256-verified Android CLI and updates installation diagnostics and license-consent documentation.
- Removes the legacy installer projects, supporting models and parsers, and associated build dependencies.
- Introduces a simplified JDK installer and updates tests, workload-feed references, and contributor guidance.
| File | Description |
|---|---|
| tools/workload-dependencies/WorkloadDependencies.proj | Uses the relocated workload manifest feed. |
| tests/Xamarin.Android.Tools.AndroidSdk-Tests/Xamarin.Android.Tools.AndroidSdk-Tests.csproj | Removes legacy installer and ZIP dependencies. |
| src/Xamarin.Installer.Common/Xamarin.Installer.Common/XmlElementExtensions.cs | Removes legacy XML helpers. |
| src/Xamarin.Installer.Common/Xamarin.Installer.Common/OperationStatus.cs | Removes legacy operation status. |
| src/Xamarin.Installer.Common/Xamarin.Installer.Common/Log.cs | Removes legacy logging infrastructure. |
| src/Xamarin.Installer.Common/Xamarin.Installer.Common/InstallationProgressEventArgs.cs | Removes legacy progress events. |
| src/Xamarin.Installer.Common/Xamarin.Installer.Common/ILogAdapter.cs | Removes legacy logging interfaces. |
| src/Xamarin.Installer.Common/Xamarin.Installer.Common/Extensions.Version.cs | Removes legacy version helpers. |
| src/Xamarin.Installer.Common/Xamarin.Installer.Common/Extensions.String.cs | Removes legacy string helpers. |
| src/Xamarin.Installer.Common/Xamarin.Installer.Common/Extensions.cs | Removes shared installer extensions. |
| src/Xamarin.Installer.Common/Xamarin.Installer.Common.csproj | Removes the common installer project. |
| src/Xamarin.Installer.Common/Properties/Resources.Designer.cs | Removes legacy resource accessors. |
| src/Xamarin.Installer.Common/Properties/AssemblyInfoTemplate.tt | Removes assembly metadata generation template. |
| src/Xamarin.Installer.Common/Properties/AssemblyInfoTemplate.cs | Removes generated assembly metadata. |
| src/Xamarin.Installer.Common/Properties/AssemblyInfo.cs | Removes common installer assembly attributes. |
| src/Xamarin.Installer.Build.Tasks/Xamarin.Installer.Common.targets | Supplies CLI pins, hashes, and task parameters. |
| src/Xamarin.Installer.Build.Tasks/Xamarin.Installer.Common.props | Removes the legacy feed-version default. |
| src/Xamarin.Installer.Build.Tasks/Xamarin.Installer.Build.Tasks.csproj | Replaces legacy references with shared Android tooling. |
| src/Xamarin.Installer.Build.Tasks/Properties/Resources.resx | Updates license guidance and CLI failure messages. |
| src/Xamarin.Installer.Build.Tasks/Properties/Resources.Designer.cs | Updates installation resource accessors. |
| src/Xamarin.Installer.Build.Tasks/JavaDependencyInstaller.cs | Adds standalone Microsoft JDK download and extraction support. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Xamarin/XamarinPackage.cs | Removes Xamarin package representation. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/ParserErrorLevel.cs | Removes parser error levels. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/MonitorWithTotalProgress.cs | Removes legacy progress aggregation. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/LocalManifestProvider.cs | Removes manifest caching infrastructure. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/JavaDependencyInstaller.cs | Removes the manifest-backed JDK installer. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/IProgressMonitor.cs | Removes installer progress interfaces. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Helpers.cs | Removes manifest parsing helpers. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/RemotePackageMetadata.cs | Removes remote package metadata. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/TypeDetailsSystemImageParser.cs | Removes system-image metadata parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/TypeDetailsSourceParser.cs | Removes source-package metadata parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/TypeDetailsPlatformParser.cs | Removes platform metadata parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/TypeDetailsParser.cs | Removes shared type-detail parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/TypeDetailsMavenParser.cs | Removes Maven metadata parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/TypeDetailsGenericParser.cs | Removes generic package metadata parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/TypeDetailsExtraParser.cs | Removes extra-package metadata parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/TypeDetailsAddOnParser.cs | Removes add-on metadata parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/RevisionParser.cs | Removes manifest revision parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/RepositoryParser.cs | Removes repository manifest parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/ParserContext.cs | Removes shared parser context. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/PackageVendorParser.cs | Removes vendor metadata parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/PackageTagParser.cs | Removes package-tag parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/LicenseParser.cs | Removes license metadata parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/LibraryParser.cs | Removes individual library parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/LibrariesParser.cs | Removes library-list parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/ElementParser.cs | Removes the shared XML parser base. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/DependencyParser.cs | Removes individual dependency parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/DependenciesParser.cs | Removes dependency-list parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/ArchivesParser.cs | Removes archive-list parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/ArchivePatchParser.cs | Removes individual archive-patch parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/ArchivePatchesParser.cs | Removes archive-patch list parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/ArchiveParser.cs | Removes archive metadata parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/ArchiveMetadataExtractor.cs | Removes archive download metadata extraction. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/AddonSiteParser.cs | Removes add-on site parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Parsing/AddonList3Parser.cs | Removes add-on repository-list parsing. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/IParserErrorHandler.cs | Removes parser error handling interface. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/Extensions.IParserErrorHandler.cs | Removes parser diagnostic helpers. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/AddonSiteType.cs | Removes add-on site classification. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/GoogleV2/AddonSite.cs | Removes the add-on site model. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.XName.cs | Removes XML-name helpers. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.XElement.cs | Removes XML-element helpers. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.String.cs | Removes parsing conversion helpers. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.Properties.cs | Removes installer property conversion helpers. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IXmlLineInfo.cs | Removes XML-location formatting helpers. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.Int32.cs | Removes hash-combination helpers. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IListOfT.cs | Removes collection comparison helpers. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Extensions.IAndroidComponent.cs | Removes component cloning helpers. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Platform.cs | Removes legacy host-platform detection. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageVendor.cs | Removes package vendor model. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageTag.cs | Removes package tag model. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageMetadata.cs | Removes shared package metadata model. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/PackageLibrary.cs | Removes package library model. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/License.cs | Removes package license model. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/JdkPackage.cs | Removes manifest-backed JDK package model. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/JdkArchive.cs | Removes legacy JDK archive model. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ItemWithIDAndDisplay.cs | Removes named-item base class. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ItemWithID.cs | Removes identifier-based model base class. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ILicensesStorage.cs | Removes legacy license storage interface. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IJdkComponent.cs | Removes JDK component interface. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IArchive.cs | Removes archive metadata interface. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IAndroidComponentInternal.cs | Removes internal component lifecycle interface. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/IAndroidApiLevel.cs | Removes component API-level interface. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/HttpClientProvider.cs | Removes legacy HTTP client provider. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Dependency.cs | Removes package dependency model. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Constants.cs | Removes legacy component constants. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ConfigManager.cs | Removes SDK manager configuration storage. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/Channel.cs | Removes repository channel model. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ArchivePatch.cs | Removes archive patch model. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/ArchiveBase.cs | Removes shared archive model base. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentStatusChangeEventArgs.cs | Removes component status events. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentStatus.cs | Removes component lifecycle statuses. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoSource.cs | Removes source-package component metadata. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoMaven.cs | Removes Maven component metadata. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoGeneric.cs | Removes generic component metadata. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/Common/AndroidComponentInfoExtra.cs | Removes extra-package component metadata. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSystemImageAbi.cs | Removes legacy system-image architecture enumeration. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKPlatform.cs | Removes installer platform enumeration. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKContext.cs | Removes global installer context. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidSDKComponentInstallationResult.cs | Removes legacy installation result model. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidManifestType.cs | Removes manifest-provider selection enumeration. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidExtensions.cs | Removes legacy package revision helpers. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidComponentType.cs | Removes component type enumeration. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidAddonDependencyInfo.cs | Removes add-on dependency metadata. |
| src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK.csproj | Removes the legacy Android SDK installer project. |
| src/Xamarin.Installer.AndroidSDK/Properties/Resources.Designer.cs | Removes SDK installer resource accessors. |
| src/Xamarin.Installer.AndroidSDK/Properties/AssemblyInfo.cs | Removes SDK installer assembly attributes. |
| src/Xamarin.Installer.AndroidSDK/CodeGenerator.targets | Removes legacy component-version generation. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj | Removes the legacy installer test reference. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/OpenJdkSignatureTests.cs | Adapts signature tests to the replacement archive type. |
| Microsoft.Android.slnx | Removes deleted installer projects from the solution. |
| Documentation/guides/InstallBuildsFromMain.md | Removes the obsolete manifest-selection argument. |
| Documentation/docs-mobile/building-apps/build-targets.md | Documents CLI installation, consent, and directory defaults. |
| Documentation/docs-mobile/building-apps/build-properties.md | Marks manifest-selection properties as removed. |
| Directory.Build.props | Removes warning exemptions for deleted projects. |
| build-tools/installers/create-installers.targets | Removes legacy installer and ZIP-library package entries. |
| .github/skills/update-androidsdk-packages/SKILL.md | Updates the manifest-feed path in maintenance guidance. |
| .github/skills/update-androidsdk-packages/references/package-catalog.md | Updates the command-line-tools manifest-feed reference. |
Review effort: Balanced
Use the same per-user cache locations as `$(MavenCacheDirectory)` instead of a generic `Android/android-cli` directory: * Windows: `%LOCALAPPDATA%\dotnet-android\AndroidCli\<version>` * macOS: `~/Library/Caches/dotnet-android/AndroidCli/<version>` * Linux: `~/.cache/dotnet-android/AndroidCli/<version>` Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…o original Use the same member order, names, and structure as the original `JavaDependencyInstaller` from `Xamarin.Installer.AndroidSDK`. `GetJdkRevision()` again returns `false` when `JAVA_VERSION` is missing, and `tar` again runs in the extract directory. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ixes
aka.ms sends an unknown JDK link to an HTML page on bing.com with
status 200. The task then downloaded that page, and the signature
check failed with a misleading XA5305 error.
`GetFirstValidJdkArchiveWithVersion()` now reads the response headers
first and returns `null` for an error status or an HTML page. The
task then reports `Invalid_JavaSdkVersion`, as the old manifest-based
code did.
Also:
* Check cancellation before `RemoveJdk()`, so a canceled build keeps
the existing JDK.
* Remove `INIFileParser.dll` from packaging and signing, and remove
`$(IniParserNetstandardVersion)`. Only the removed
`Xamarin.Installer.AndroidSDK` project used it.
* Explain why the JDK is extracted next to `JdkPath`.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The new Android CLI errors used uncoded `LogError()`, so they had no
diagnostic code or documentation page. Report them with
`LogCodedError()`:
* XA5306: The Android CLI is not available for this operating
system and architecture.
* XA5307: The SHA-256 hash of the downloaded Android CLI is not
correct.
* XA5308: The Android CLI failed while it installed Android SDK
packages.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…id-cli-license # Conflicts: # build-tools/installers/create-installers.targets # src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK.csproj # src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/AndroidUtilities.cs # src/Xamarin.Installer.AndroidSDK/Xamarin.Installer.AndroidSDK/LocalSDK/LocalSDKRepository.cs # tests/Xamarin.Android.Tools.AndroidSdk-Tests/AndroidSdkInstallerTests.cs
This was referenced Nov 12, 2026
simonrozsival
approved these changes
Nov 13, 2026
7 tasks
simonrozsival
added a commit
that referenced
this pull request
Nov 13, 2026
…MABT Context: #12981 Context: https://devblogs.microsoft.com/dotnet/process-api-improvements-in-dotnet-11/ Context: https://learn.microsoft.com/visualstudio/msbuild/update-task-multithreaded After #13513, `InstallAndroidDependencies` installs SDK packages with Google's Android CLI, but it still lived in the netstandard2.0 `Xamarin.Installer.Build.Tasks.dll`. There it had to start the Android CLI, `/usr/bin/tar`, and `chmod` through `ProcessUtils`, and it could not run in multithreaded MSBuild (`-mt`). Move the task, `JavaDependencyInstaller`, and `OpenJdkSignatureVerifier` into `Microsoft.Android.Build.Tasks.dll`, which runs on .NET: * Register the task with the paired Full/Core `Runtime="NET"` `<UsingTask/>`. MABT links the existing localized messages and deploys `Xamarin.Installer.Common.props` and `.targets` to `tools`, so `Xamarin.Android.Common.targets` and the localization files are unchanged. Remove `Xamarin.Installer.Build.Tasks.csproj`. * Run the Android CLI with `Process.ReadAllLinesAsync()` and `WaitForExitAsync()`, keeping only the tail of its output as before, and kill its process tree when the task fails or is canceled. Extract JDK `.tar.gz` archives with `TarFile`, and mark the downloaded Android CLI executable with `File.SetUnixFileMode()`. * Derive from `MultithreadedAndroidTask` with `[MSBuildMultiThreadableTask]` and `ICancelableTask`. `RunTask()` runs the existing async workflow on the thread pool and forwards log messages to the thread that called `Execute()`, as `AsyncTask` did. Environment variables, the child process start info, and all paths come from `TaskEnvironment`; resolved paths are passed around as `AbsolutePath`. The default SDK and JDK locations come from the task's `LOCALAPPDATA` or `HOME`. Three analyzer findings are suppressed with justifications: `Process.Start()` (its `ProcessStartInfo` comes from `TaskEnvironment.GetProcessStartInfo()`), `Path.GetTempFileName()` (no `TaskEnvironment` alternative yet), and `Environment.GetFolderPath(ProgramFiles)` (a machine location). `OpenJdkSignatureTests` and the unit tests that create the task move to the net12.0 `Microsoft.Android.Build.Tasks.Tests`. The fake Android CLI test now also checks that a relative `AndroidSdkPath` resolves against the project directory and that messages are logged on the `Execute()` thread. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival
added a commit
that referenced
this pull request
Nov 13, 2026
…MABT Context: #12981 Context: https://devblogs.microsoft.com/dotnet/process-api-improvements-in-dotnet-11/ Context: https://learn.microsoft.com/visualstudio/msbuild/update-task-multithreaded After #13513, `InstallAndroidDependencies` installs SDK packages with Google's Android CLI, but it still lived in the netstandard2.0 `Xamarin.Installer.Build.Tasks.dll`. There it had to start the Android CLI, `/usr/bin/tar`, and `chmod` through `ProcessUtils`, and it could not run in multithreaded MSBuild (`-mt`). Move the task, `JavaDependencyInstaller`, and `OpenJdkSignatureVerifier` into `Microsoft.Android.Build.Tasks.dll`, which runs on .NET: * Register the task with the paired Full/Core `Runtime="NET"` `<UsingTask/>`. MABT links the existing localized messages and deploys `Xamarin.Installer.Common.props` and `.targets` to `tools`, so `Xamarin.Android.Common.targets` and the localization files are unchanged. Remove `Xamarin.Installer.Build.Tasks.csproj`. * Run the Android CLI with `Process.ReadAllLinesAsync()` and `WaitForExitAsync()`, keeping only the tail of its output as before, and kill its process tree when the task fails or is canceled. Extract JDK `.tar.gz` archives with `TarFile`, and mark the downloaded Android CLI executable with `File.SetUnixFileMode()`. * Derive from `MultithreadedAndroidTask` with `[MSBuildMultiThreadableTask]` and `ICancelableTask`. `RunTask()` runs the existing async workflow on the thread pool and forwards log messages to the thread that called `Execute()`, as `AsyncTask` did. Environment variables, the child process start info, and all paths come from `TaskEnvironment`; resolved paths are passed around as `AbsolutePath`. The default SDK and JDK locations come from the task's `LOCALAPPDATA` or `HOME`. Three analyzer findings are suppressed with justifications: `Process.Start()` (its `ProcessStartInfo` comes from `TaskEnvironment.GetProcessStartInfo()`), `Path.GetTempFileName()` (no `TaskEnvironment` alternative yet), and `Environment.GetFolderPath(ProgramFiles)` (a machine location). `OpenJdkSignatureTests` and the unit tests that create the task move to the net12.0 `Microsoft.Android.Build.Tasks.Tests`. The fake Android CLI test now also checks that a relative `AndroidSdkPath` resolves against the project directory and that messages are logged on the `Execute()` thread. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival
added a commit
that referenced
this pull request
Nov 13, 2026
Coxntext: #13513 The legacy Android SDK installer used `Mono.Unix.Native.Syscall.chmod` to set file permissions. #13513 removed that installer in favor of the Android CLI, removing the last product call to Mono.Unix. The shared MSBuild references still restore the package, and the build still copies and packages its managed and native libraries even though there are no remaining callers. Remove the package reference and version properties, the native-library copy and macOS universal-library build, the SDK packaging and signing entries, and the obsolete configuration and test import. This removes the dependency; it does not replace all Unix interop with .NET APIs. Existing libc and `chmod` uses remain unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


The
InstallAndroidDependenciestarget used our own copy of the Android SDK manager (Xamarin.Installer.AndroidSDKandXamarin.Installer.Common) to read the Xamarin manifest, download archives, and extract them. That is a lot of code to maintain. Google now ships the Android CLI, which does the same job.This PR removes both projects.
InstallAndroidDependenciesnow:Xamarin.Installer.Common.targets.dotnet-android/AndroidCli/<version>, in the same per-user cache folder as$(MavenCacheDirectory). For example, on Windows this is%LOCALAPPDATA%\dotnet-android\AndroidCli\<version>.android sdk install.After the CLI exits, the task checks the SDK again, because the CLI can exit with 0 for an unknown package.
JDK installation stays. A simplified
JavaDependencyInstalleris copied from the removed project, and it now downloads from aka.ms/download-jdk. OpenJDK signature verification (XA5305) does not change.The Android CLI accepts the Android SDK licenses without a prompt. Thus
$(AcceptAndroidSDKLicenses)is the only consent, and its error message now links to the Android SDK License Agreement.These properties are removed:
$(AndroidManifestType),$(AndroidManifestSource), and$(_AndroidIgnoreSdkArchiveChecksumErrors). The docs list them as removed in .NET 12.Known limitation: Google does not ship a Windows Arm64 build of the Android CLI, so on Windows Arm64 the task reports an unsupported platform error.
Testing
With a local SDK build on Windows x64:
Result: passed, 73 of 73. This includes a new test that checks the arguments passed to a fake Android CLI. The run downloaded the Android CLI to
%LOCALAPPDATA%\dotnet-android\AndroidCli\1.1.16717390\android-cli.exe.I also ran
android sdk install platform-toolsinto an empty folder by hand. The CLI wrotelicenses/android-sdk-licenseand did not show a prompt.