From 4b93b4bb605aa238ccf4e54f153f6151cb9634c3 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 2 Apr 2026 14:27:53 -0500 Subject: [PATCH 1/2] TryGetPlatformDirectoryFromApiLevel: fall back from android-{major} to android-{major}.0 Starting with API 37, Google's SDK Manager installs platforms to android-37.0 instead of android-37. Add a fallback so that when the integer-based directory doesn't exist, we also try the .0 suffix. Fixes: https://github.com/dotnet/android-tools/issues/319 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../AndroidSdkInfo.cs | 9 +++++ .../AndroidSdkInfoTests.cs | 35 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/Xamarin.Android.Tools.AndroidSdk/AndroidSdkInfo.cs b/src/Xamarin.Android.Tools.AndroidSdk/AndroidSdkInfo.cs index d6913e65..66a308ac 100644 --- a/src/Xamarin.Android.Tools.AndroidSdk/AndroidSdkInfo.cs +++ b/src/Xamarin.Android.Tools.AndroidSdk/AndroidSdkInfo.cs @@ -120,6 +120,15 @@ public string GetPlatformDirectoryFromId (string id) if (dir != null && Directory.Exists (dir)) return dir; + // Starting with API 37, Google's SDK Manager installs platforms to + // "android-37.0" instead of "android-37". Try the "{major}.0" fallback. + // See: https://github.com/dotnet/android-tools/issues/319 + if (int.TryParse (id, out _)) { + dir = GetPlatformDirectoryFromId (id + ".0"); + if (Directory.Exists (dir)) + return dir; + } + return null; } diff --git a/tests/Xamarin.Android.Tools.AndroidSdk-Tests/AndroidSdkInfoTests.cs b/tests/Xamarin.Android.Tools.AndroidSdk-Tests/AndroidSdkInfoTests.cs index e7a25217..1db8fd4d 100644 --- a/tests/Xamarin.Android.Tools.AndroidSdk-Tests/AndroidSdkInfoTests.cs +++ b/tests/Xamarin.Android.Tools.AndroidSdk-Tests/AndroidSdkInfoTests.cs @@ -633,6 +633,41 @@ public void TryGetPlatformDirectoryFromApiLevel_MinorVersionDoesNotFallback () } } + [Test] + public void TryGetPlatformDirectoryFromApiLevel_MajorFallsBackToMajorDotZero () + { + // Starting with API 37, Google installs platforms to "android-37.0" + // instead of "android-37". Verify the fallback works. + // See: https://github.com/dotnet/android-tools/issues/319 + CreateSdks (out string root, out string jdk, out string ndk, out string sdk); + + // Only create android-37.0, not android-37 + var platformsPath = Path.Combine (sdk, "platforms"); + var platform370Path = Path.Combine (platformsPath, "android-37.0"); + Directory.CreateDirectory (platform370Path); + File.WriteAllText (Path.Combine (platform370Path, "android.jar"), ""); + + var logs = new StringWriter (); + Action logger = (level, message) => { + logs.WriteLine ($"[{level}] {message}"); + }; + + try { + var info = new AndroidSdkInfo (logger, androidSdkPath: sdk, androidNdkPath: ndk, javaSdkPath: jdk); + var versions = new AndroidVersions (new [] { + new AndroidVersion (37, "17.0"), + }); + + // Requesting "37" should fall back to android-37.0 + var dir37 = info.TryGetPlatformDirectoryFromApiLevel ("37", versions); + Assert.IsNotNull (dir37, "Should fall back from android-37 to android-37.0"); + Assert.AreEqual (platform370Path, dir37); + } + finally { + Directory.Delete (root, recursive: true); + } + } + [Test] public void GetBuildToolsPaths_StableVersionsFirst () { From b27b64f1d7d44189373a00d19957558e545741eb Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 2 Apr 2026 16:11:25 -0500 Subject: [PATCH 2/2] Apply .0 fallback to IsPlatformInstalled as well IsPlatformInstalled(37) would return false when only android-37.0 exists on disk. Apply the same major.0 fallback for consistency with TryGetPlatformDirectoryFromApiLevel, and add a test assertion. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Xamarin.Android.Tools.AndroidSdk/AndroidSdkInfo.cs | 4 +++- .../AndroidSdkInfoTests.cs | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Tools.AndroidSdk/AndroidSdkInfo.cs b/src/Xamarin.Android.Tools.AndroidSdk/AndroidSdkInfo.cs index 66a308ac..1e843a01 100644 --- a/src/Xamarin.Android.Tools.AndroidSdk/AndroidSdkInfo.cs +++ b/src/Xamarin.Android.Tools.AndroidSdk/AndroidSdkInfo.cs @@ -134,7 +134,9 @@ public string GetPlatformDirectoryFromId (string id) public bool IsPlatformInstalled (int apiLevel) { - return apiLevel != 0 && Directory.Exists (GetPlatformDirectory (apiLevel)); + return apiLevel != 0 && + (Directory.Exists (GetPlatformDirectory (apiLevel)) || + Directory.Exists (GetPlatformDirectoryFromId (apiLevel + ".0"))); } public string? AndroidNdkPath { diff --git a/tests/Xamarin.Android.Tools.AndroidSdk-Tests/AndroidSdkInfoTests.cs b/tests/Xamarin.Android.Tools.AndroidSdk-Tests/AndroidSdkInfoTests.cs index 1db8fd4d..9461f1cd 100644 --- a/tests/Xamarin.Android.Tools.AndroidSdk-Tests/AndroidSdkInfoTests.cs +++ b/tests/Xamarin.Android.Tools.AndroidSdk-Tests/AndroidSdkInfoTests.cs @@ -662,6 +662,9 @@ public void TryGetPlatformDirectoryFromApiLevel_MajorFallsBackToMajorDotZero () var dir37 = info.TryGetPlatformDirectoryFromApiLevel ("37", versions); Assert.IsNotNull (dir37, "Should fall back from android-37 to android-37.0"); Assert.AreEqual (platform370Path, dir37); + + // IsPlatformInstalled should also find android-37.0 + Assert.IsTrue (info.IsPlatformInstalled (37), "IsPlatformInstalled should find android-37.0"); } finally { Directory.Delete (root, recursive: true);