From 4e63b5e10d9d3292c93a1526df1f570aafcbd384 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 14:49:03 +0000 Subject: [PATCH 1/2] Initial plan From 6973d03c12c7d0c804052f72e284a56425deb9c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 15:22:10 +0000 Subject: [PATCH 2/2] fix: avoid ResolveAndroidTooling NRE when SDK resolution fails Agent-Logs-Url: https://github.com/dotnet/android/sessions/ab9b627b-2492-407c-b80c-661d58857a34 Co-authored-by: davidnguyen-tech <87228593+davidnguyen-tech@users.noreply.github.com> --- .../Tasks/ResolveAndroidTooling.cs | 12 +++++-- .../Tasks/ResolveSdksTaskTests.cs | 31 +++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAndroidTooling.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAndroidTooling.cs index c20e0bc0973..7d07fecaa32 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAndroidTooling.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAndroidTooling.cs @@ -90,11 +90,17 @@ public override bool RunTask () AndroidApiLevel = GetMaxStableApiLevel ().ToString (); } + var androidSdk = MonoAndroidHelper.AndroidSdk; + if (androidSdk == null || AndroidSdkPath.IsNullOrEmpty ()) { + Log.LogCodedError ("XA5300", Properties.Resources.XA5300_Android_SDK); + return false; + } + string toolsZipAlignPath = Path.Combine (AndroidSdkPath, "tools", ZipAlign); bool findZipAlign = (ZipAlignPath.IsNullOrEmpty () || !Directory.Exists (ZipAlignPath)) && !File.Exists (toolsZipAlignPath); - var lintPaths = MonoAndroidHelper.AndroidSdk.GetCommandLineToolsPaths (CommandLineToolsVersion ?? "") - .SelectMany (p => new[]{ + var lintPaths = androidSdk.GetCommandLineToolsPaths (CommandLineToolsVersion ?? "") + .SelectMany (p => new [] { p, Path.Combine (p, "bin"), }); @@ -107,7 +113,7 @@ public override bool RunTask () } } - foreach (var dir in MonoAndroidHelper.AndroidSdk.GetBuildToolsPaths (AndroidSdkBuildToolsVersion ?? "")) { + foreach (var dir in androidSdk.GetBuildToolsPaths (AndroidSdkBuildToolsVersion ?? "")) { Log.LogDebugMessage ("Trying build-tools path: {0}", dir); if (dir == null || !Directory.Exists (dir)) continue; diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ResolveSdksTaskTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ResolveSdksTaskTests.cs index f9bf21dc4ac..23533f76703 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ResolveSdksTaskTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ResolveSdksTaskTests.cs @@ -219,5 +219,36 @@ public void ResolveSdkTiming () Directory.Delete (Path.Combine (Root, path), recursive: true); } + [Test] + public void ResolveAndroidToolingWithMissingResolvedSdkDoesNotThrow () + { + var path = Path.Combine (Path.GetTempPath (), "xa-tests", nameof (ResolveAndroidToolingWithMissingResolvedSdkDoesNotThrow), Guid.NewGuid ().ToString ("N")); + Directory.CreateDirectory (path); + var errors = new List (); + var originalAndroidSdk = MonoAndroidHelper.AndroidSdk; + try { + MonoAndroidHelper.AndroidSdk = null; + IBuildEngine engine = new MockBuildEngine (TestContext.Out, errors); + var androidTooling = new Xamarin.Android.Tasks.ResolveAndroidTooling { + BuildEngine = engine, + AndroidSdkPath = path, + AndroidSdkBuildToolsVersion = "36.0.0", + TargetPlatformVersion = "37.0", + AotAssemblies = false, + SequencePointsMode = "None", + AndroidApplication = true, + }; + + Assert.IsFalse (androidTooling.Execute (), "ResolveAndroidTooling should fail when SDK resolution has not succeeded."); + Assert.AreEqual ("37", androidTooling.AndroidApiLevel, "AndroidApiLevel should still be calculated for dependency resolution."); + Assert.IsTrue (errors.Any (e => e.Code == "XA5300"), "XA5300 should be logged when Android SDK tooling is unavailable."); + Assert.IsFalse (errors.Any (e => e.Code == "XARAT7001"), "ResolveAndroidTooling should not throw when AndroidSdk is unavailable."); + } finally { + MonoAndroidHelper.AndroidSdk = originalAndroidSdk; + if (Directory.Exists (path)) + Directory.Delete (path, recursive: true); + } + } + } }