diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets index 411e06d32a9..eed1d4765df 100644 --- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets +++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets @@ -234,7 +234,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. CreatePackagePerAbi="$(AndroidCreatePackagePerAbi)" AssetsDirectory="$(MonoAndroidAssetsDirIntermediate)" AdditionalAndroidAssetPaths="@(LibraryAssetDirectories)" - AndroidSdkPlatform="$(_AndroidApiLevel)" + AndroidApiLevel="$(_AndroidApiLevel)" JavaDesignerOutputDirectory="$(AaptTemporaryDirectory)" ManifestFiles="$(IntermediateOutputPath)android\AndroidManifest.xml" ProtobufFormat="$(_ProtobufFormat)" diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Tooling.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Tooling.targets index e33e9215ff6..e554aec324c 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Tooling.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Tooling.targets @@ -70,7 +70,7 @@ This file contains .NET 6+ calls to the and diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/Aapt2Link.cs b/src/Xamarin.Android.Build.Tasks/Tasks/Aapt2Link.cs index 847aebeba55..7bdaf4c8589 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/Aapt2Link.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/Aapt2Link.cs @@ -58,7 +58,7 @@ public class Aapt2Link : Aapt2 { public string? UncompressedFileExtensions { get; set; } - public string? AndroidSdkPlatform { get; set; } + public string AndroidApiLevel { get; set; } = ""; public string? VersionCodePattern { get; set; } @@ -151,8 +151,12 @@ string [] GenerateCommandLineCommands (string ManifestFile, string? currentAbi, string manifestDir = Path.Combine (Path.GetDirectoryName (ManifestFile), currentAbi != null ? currentAbi : "manifest"); Directory.CreateDirectory (manifestDir); string manifestFile = Path.Combine (manifestDir, Path.GetFileName (ManifestFile)); + string targetSdkVersion = AndroidApiLevel; + if (MonoAndroidHelper.TryParseApiLevel (targetSdkVersion, out Version v)) { + targetSdkVersion = v.Major.ToString (CultureInfo.InvariantCulture); + } ManifestDocument manifest = new ManifestDocument (ManifestFile); - manifest.TargetSdkVersion = AndroidSdkPlatform; + manifest.TargetSdkVersion = targetSdkVersion; if (!VersionCodePattern.IsNullOrEmpty ()) { try { manifest.CalculateVersionCode (currentAbi, VersionCodePattern, VersionCodeProperties); diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CheckGoogleSdkRequirements.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CheckGoogleSdkRequirements.cs index bdea41871d4..88694667e86 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/CheckGoogleSdkRequirements.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/CheckGoogleSdkRequirements.cs @@ -1,15 +1,8 @@ #nullable enable using System; -using System.Collections.Generic; -using Microsoft.Build.Utilities; -using Microsoft.Build.Framework; -using System.IO; -using System.Linq; - -using Java.Interop.Tools.Cecil; -using Xamarin.Android.Tools; using Microsoft.Android.Build.Tasks; +using Microsoft.Build.Framework; namespace Xamarin.Android.Tasks { @@ -17,15 +10,8 @@ public class CheckGoogleSdkRequirements : AndroidTask { public override string TaskPrefix => "CGS"; - /// - /// This will be blank for .NET 5 builds - /// - public string? TargetFrameworkVersion { get; set; } - - /// - /// This is used instead of TargetFrameworkVersion for .NET 5 builds - /// - public int ApiLevel { get; set; } + [Required] + public string AndroidApiLevel { get; set; } = ""; [Required] public string ManifestFile { get; set; } = ""; @@ -34,15 +20,18 @@ public override bool RunTask () { ManifestDocument manifest = new ManifestDocument (ManifestFile); - var compileSdk = TargetFrameworkVersion.IsNullOrEmpty () ? - ApiLevel : - MonoAndroidHelper.SupportedVersions.GetApiLevelFromFrameworkVersion (TargetFrameworkVersion); + int? compileSdk = null; + + if (MonoAndroidHelper.TryParseApiLevel (AndroidApiLevel, out Version version)) { + compileSdk = version.Major; + } if (!int.TryParse (manifest.GetMinimumSdk (), out int minSdk)) { minSdk = 1; } if (!int.TryParse (manifest.GetTargetSdk (), out int targetSdk)) { - targetSdk = compileSdk ?? ApiLevel; + // 21 is minimum supported for .NET 6+, but should be better than putting 1 here. + targetSdk = compileSdk ?? 21; } //We should throw a warning if the targetSdkVersion is lower than compileSdkVersion(TargetFrameworkVersion). diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs index 86d7da7b765..bf709baf4c6 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs @@ -47,8 +47,6 @@ public class GenerateJavaStubs : AndroidTask public bool Debug { get; set; } - [Required] - public string AndroidSdkPlatform { get; set; } = ""; [Required] public string OutputDirectory { get; set; } = ""; @@ -237,7 +235,7 @@ internal static Dictionary MaybeGetArchAssemblies (Dictionary bool success = true; if (generateJavaCode && RunCheckedBuild) { - success = jcwGenerator.Generate (AndroidSdkPlatform, outputPath: Path.Combine (OutputDirectory, "src"), ApplicationJavaClass); + success = jcwGenerator.Generate (outputPath: Path.Combine (OutputDirectory, "src"), ApplicationJavaClass); generatedJavaFiles = jcwGenerator.GeneratedJavaFiles; } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateMainAndroidManifest.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateMainAndroidManifest.cs index 9d9782f64ce..dcece671899 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateMainAndroidManifest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateMainAndroidManifest.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.Android.Build.Tasks; using Microsoft.Build.Framework; @@ -19,7 +20,8 @@ public class GenerateMainAndroidManifest : AndroidTask [Required] public string AndroidRuntime { get; set; } = ""; public string? AndroidSdkDir { get; set; } - public string? AndroidSdkPlatform { get; set; } + [Required] + public string AndroidApiLevel { get; set; } = ""; public string? ApplicationJavaClass { get; set; } public string? ApplicationLabel { get; set; } public string? BundledWearApplicationName { get; set; } @@ -91,6 +93,11 @@ public override bool RunTask () IList MergeManifest (NativeCodeGenState codeGenState, Dictionary userAssemblies) { + string targetSdkVersion = AndroidApiLevel; + if (MonoAndroidHelper.TryParseApiLevel (targetSdkVersion, out Version version)) { + targetSdkVersion = version.Major.ToString (CultureInfo.InvariantCulture); + } + var manifest = new ManifestDocument (ManifestTemplate) { PackageName = PackageName, VersionName = VersionName, @@ -98,7 +105,7 @@ IList MergeManifest (NativeCodeGenState codeGenState, Dictionary "GAD"; [Required] - public int AndroidApiLevel { get; set; } + public string AndroidApiLevel { get; set; } = ""; public string? ProductVersion { get; set; } @@ -34,9 +34,20 @@ public override bool RunTask () constants.Add (new TaskItem ("__MOBILE__")); constants.Add (new TaskItem ("__ANDROID__")); - for (int i = 1; i <= AndroidApiLevel; ++i) { + if (!MonoAndroidHelper.TryParseApiLevel (AndroidApiLevel, out var apiLevel)) { + return false; + } + + for (int i = 1; i <= apiLevel.Major; ++i) { constants.Add (new TaskItem ($"__ANDROID_{i}__")); } + // TODO: We're just going to assume that there is a minor release for every major release from API-36.1 onward… + for (int i = 36; i < apiLevel.Major; ++i) { + constants.Add (new TaskItem ($"__ANDROID_{i}_1__")); + } + if (apiLevel.Minor != 0) { + constants.Add (new TaskItem ($"__ANDROID_{apiLevel.Major}_{apiLevel.Minor}__")); + } AndroidDefineConstants = constants.ToArray (); diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs index ea02a64f93e..61d407cb9b5 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs @@ -148,8 +148,8 @@ int GetNdkApiLevel (NdkTools ndk, AndroidTargetArch arch) level = manifest.MinSdkVersion.Value; } else if (int.TryParse (MinimumSupportedApiLevel, out level)) { // level already set - } else if (int.TryParse (AndroidApiLevel, out level)) { - // level already set + } else if (MonoAndroidHelper.TryParseApiLevel (AndroidApiLevel, out Version version)) { + level = version.Major; } else { // Probably not ideal! level = MonoAndroidHelper.SupportedVersions.MaxStableVersion?.ApiLevel ?? 21; diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GetJavaPlatformJar.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GetJavaPlatformJar.cs index ae82bde9f2e..8e6dfa519f3 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GetJavaPlatformJar.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GetJavaPlatformJar.cs @@ -21,7 +21,7 @@ public class GetJavaPlatformJar : AndroidTask private XNamespace androidNs = "http://schemas.android.com/apk/res/android"; [Required] - public string AndroidSdkPlatform { get; set; } = ""; + public string AndroidApiLevel { get; set; } = ""; public string? AndroidManifest { get; set; } @@ -45,7 +45,7 @@ public class GetJavaPlatformJar : AndroidTask public override bool RunTask () { - var platform = AndroidSdkPlatform; + var platform = AndroidApiLevel; XAttribute? target_sdk = null; @@ -117,14 +117,14 @@ public override bool RunTask () string GetTargetSdkVersion (string target, XAttribute? target_sdk) { - string targetFrameworkVersion = MonoAndroidHelper.SupportedVersions.GetIdFromApiLevel (AndroidSdkPlatform) ?? ""; + string targetFrameworkVersion = MonoAndroidHelper.SupportedVersions.GetIdFromApiLevel (AndroidApiLevel) ?? ""; string targetSdkVersion = MonoAndroidHelper.SupportedVersions.GetIdFromApiLevel (target) ?? ""; // For .NET 6+ projects, use TargetPlatformVersion directly string targetPlatformVersionDisplay = !TargetPlatformVersion.IsNullOrEmpty () ? TargetPlatformVersion : ""; - if (!int.TryParse (targetFrameworkVersion, out int frameworkSdk)) { - // AndroidSdkPlatform is likely a *preview* API level; use it. + if (!MonoAndroidHelper.TryParseApiLevel (targetFrameworkVersion, out var frameworkSdk)) { + // AndroidApiLevel is likely a *preview* API level; use it. Log.LogWarningForXmlNode ( code: "XA4211", file: AndroidManifest, @@ -138,8 +138,8 @@ string GetTargetSdkVersion (string target, XAttribute? target_sdk) ); return targetFrameworkVersion; } - if (int.TryParse (targetSdkVersion, out int targetSdk) && - targetSdk < frameworkSdk) { + if (MonoAndroidHelper.TryParseApiLevel (targetSdkVersion, out var targetSdk) && + targetSdk.Major < frameworkSdk.Major) { Log.LogWarningForXmlNode ( code: "XA4211", file: AndroidManifest, diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ReadAndroidManifest.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ReadAndroidManifest.cs index 1d2d6392dba..9a31cd7487e 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/ReadAndroidManifest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/ReadAndroidManifest.cs @@ -5,6 +5,8 @@ using System.IO; using Xamarin.Android.Tools; using Microsoft.Android.Build.Tasks; +using System; +using System.Globalization; namespace Xamarin.Android.Tasks { @@ -66,7 +68,17 @@ public override bool RunTask () var attribute = uses_library.Attribute (androidNs + "name"); if (attribute != null && !attribute.Value.IsNullOrEmpty ()) { var required = uses_library.Attribute (androidNs + "required")?.Value; - var path = Path.Combine (AndroidSdkDirectory, "platforms", $"android-{AndroidApiLevel}", "optional", $"{attribute.Value}.jar"); + string apiLevel; + if (MonoAndroidHelper.TryParseApiLevel (AndroidApiLevel, out Version version)) { + if (version.Minor == 0) { + apiLevel = version.Major.ToString (CultureInfo.InvariantCulture); + } else { + apiLevel = version.ToString (); + } + } else { + apiLevel = AndroidApiLevel; + } + var path = Path.Combine (AndroidSdkDirectory, "platforms", $"android-{apiLevel}", "optional", $"{attribute.Value}.jar"); if (File.Exists (path)) { libraries.Add (new TaskItem (path)); } else { diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAndroidTooling.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAndroidTooling.cs index 5ea189b934c..e01cbbbebd1 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAndroidTooling.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveAndroidTooling.cs @@ -81,7 +81,11 @@ public override bool RunTask () { // This should be 31.0, 32.0, etc. if (Version.TryParse (TargetPlatformVersion, out Version v)) { - AndroidApiLevel = v.Major.ToString (); + if (v.Minor == 0) { + AndroidApiLevel = v.Major.ToString (CultureInfo.InvariantCulture); + } else { + AndroidApiLevel = v.ToString (); + } } else { AndroidApiLevel = GetMaxStableApiLevel ().ToString (); } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/CheckGoogleSdkRequirementsTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/CheckGoogleSdkRequirementsTests.cs index 5d5e9a6d8c4..4948f9b733a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/CheckGoogleSdkRequirementsTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/CheckGoogleSdkRequirementsTests.cs @@ -49,7 +49,7 @@ public void CheckManifestIsOK () { var task = new CheckGoogleSdkRequirements () { BuildEngine = engine, - TargetFrameworkVersion = "v9.0", + AndroidApiLevel = "28", ManifestFile = CreateManiestFile (10, 28), }; Assert.True (task.Execute (), "Task should have succeeded."); @@ -62,7 +62,7 @@ public void CheckManifestTargetSdkLowerThanCompileSdk () { var task = new CheckGoogleSdkRequirements () { BuildEngine = engine, - TargetFrameworkVersion = "v9.0", + AndroidApiLevel = "28", ManifestFile = CreateManiestFile (10, 27), }; Assert.True (task.Execute (), "Task should have succeeded."); @@ -75,12 +75,12 @@ public void CheckManifestCompileSdkLowerThanTargetSdk () { var task = new CheckGoogleSdkRequirements () { BuildEngine = engine, - TargetFrameworkVersion = "v8.1", + AndroidApiLevel = "27", ManifestFile = CreateManiestFile (10, 28), }; Assert.True (task.Execute (), "Task should have succeeded."); Assert.AreEqual (0, errors.Count, "There should be 1 error reported."); - Assert.AreEqual (1, warnings.Count, "There should be 0 warnings reported."); + Assert.AreEqual (1, warnings.Count, "There should be 1 warning reported."); } [Test] @@ -88,12 +88,12 @@ public void CheckManifestMinSdkLowerThanTargetSdk () { var task = new CheckGoogleSdkRequirements () { BuildEngine = engine, - TargetFrameworkVersion = "v8.1", + AndroidApiLevel = "27", ManifestFile = CreateManiestFile (28, 27), }; Assert.True (task.Execute (), "Task should have succeeded."); Assert.AreEqual (0, errors.Count, "There should be 0 error reported."); - Assert.AreEqual (1, warnings.Count, "There should be 1 warnings reported."); + Assert.AreEqual (1, warnings.Count, "There should be 1 warning reported."); } } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/JCWGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/JCWGenerator.cs index d466ab85b64..3bb8c5a6ee4 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/JCWGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/JCWGenerator.cs @@ -53,17 +53,16 @@ public JCWGenerator (TaskLoggingHelper log, JCWGeneratorContext context) public List GeneratedJavaFiles { get; } = []; - public bool Generate (string androidSdkPlatform, string outputPath, string applicationJavaClass) + public bool Generate (string outputPath, string applicationJavaClass) { return ProcessTypes ( generateCode: true, - androidSdkPlatform, outputPath, applicationJavaClass ); } - bool ProcessTypes (bool generateCode, string androidSdkPlatform, string? outputPath, string? applicationJavaClass) + bool ProcessTypes (bool generateCode, string? outputPath, string? applicationJavaClass) { if (generateCode && outputPath.IsNullOrEmpty ()) { throw new ArgumentException ("must not be null or empty", nameof (outputPath)); diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 6350bee47d2..f52d9f1c47e 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1590,7 +1590,6 @@ because xbuild doesn't support framework reference assemblies. GeneratedJavaFiles="@(_GeneratedJavaFiles)" ErrorOnCustomJavaObject="$(AndroidErrorOnCustomJavaObject)" Debug="$(AndroidIncludeDebugSymbols)" - AndroidSdkPlatform="$(_AndroidApiLevel)" OutputDirectory="$(IntermediateOutputPath)android" PackageNamingPolicy="$(AndroidPackageNamingPolicy)" ApplicationJavaClass="$(AndroidApplicationJavaClass)" @@ -1633,7 +1632,7 @@ because xbuild doesn't support framework reference assemblies.