Skip to content

Commit 26a689e

Browse files
committed
[XABT] Do not prefer NDKMinimumApiAvailable
I noticed that we were not writing a valid `minSdkVersion` value to the generated `AndroidManifest.xml` file for projects which included a manifest that declared a `targetSdkVersion`. In these cases, we would always write a `minSdkVersion` of `19` to the manifest file, as this is the min version that our NDK supports. Fix this to always write the value of `$(SupportedOSPlatformVersion)`. If this value is not explicitly set in the project file, it will default to `$(TargetPlatformVersion)`.
1 parent c31f3ed commit 26a689e

File tree

8 files changed

+82
-45
lines changed

8 files changed

+82
-45
lines changed

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Xml.XPath;
99
using Xamarin.Tools.Zip;
1010
using System.Collections.Generic;
11+
using Xamarin.Android.Tools;
1112

1213
namespace Xamarin.Android.Build.Tests
1314
{
@@ -964,5 +965,56 @@ public void ExportedErrorMessage ()
964965
Assert.IsTrue (b.LastBuildOutput.ContainsText ($"AndroidManifest.xml(12,5): java{extension} error AMM0000:"), "Should recieve AMM0000 error");
965966
Assert.IsTrue (b.LastBuildOutput.ContainsText ("Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported`"), "Should recieve AMM0000 error");
966967
}
968+
969+
// TODO: <uses-sdk android:minSdkVersion="32" android:targetSdkVersion="32" />
970+
// Causes warning: D8 : warning : An API level of 32 is not supported by this compiler. Please use an API level of 31 or earlier
971+
// Add a 32 parameter here when we get a newer version of r8.
972+
[Test]
973+
974+
[TestCase (0, true)]
975+
[TestCase (0, false)]
976+
[TestCase (21, true)]
977+
[TestCase (31, false)]
978+
public void SupportedOSPlatformVersion (int minSdkVersion, bool removeUsesSdkElement)
979+
{
980+
var proj = new XamarinAndroidApplicationProject {
981+
EnableDefaultItems = true,
982+
};
983+
984+
// Do not set project property and use default value when minSdkVersion = 0
985+
if (minSdkVersion > 0) {
986+
proj.SupportedOSPlatformVersion = minSdkVersion.ToString ();
987+
} else {
988+
minSdkVersion = XABuildConfig.AndroidDefaultTargetDotnetApiLevel;
989+
}
990+
991+
if (removeUsesSdkElement) {
992+
proj.AndroidManifest = $@"<?xml version=""1.0"" encoding=""utf-8""?>
993+
<manifest xmlns:android=""http://schemas.android.com/apk/res/android"" android:versionCode=""1"" android:versionName=""1.0"" package=""{proj.PackageName}"">
994+
<application android:label=""{proj.ProjectName}"">
995+
</application>
996+
</manifest>";
997+
}
998+
999+
// Call AccessibilityTraversalAfter from API level 22
1000+
// https://developer.android.com/reference/android/view/View#getAccessibilityTraversalAfter()
1001+
proj.MainActivity = proj.DefaultMainActivity.Replace ("button!.Click", "button!.AccessibilityTraversalAfter.ToString ();\nbutton!.Click");
1002+
1003+
var builder = CreateApkBuilder ();
1004+
Assert.IsTrue (builder.Build (proj), "`dotnet build` should succeed");
1005+
1006+
if (minSdkVersion < 22) {
1007+
StringAssertEx.Contains ("warning CA1416", builder.LastBuildOutput, "Should get warning about Android 22 API");
1008+
} else {
1009+
builder.AssertHasNoWarnings ();
1010+
}
1011+
1012+
var manifestPath = Path.Combine (Root, builder.ProjectDirectory, proj.IntermediateOutputPath, "android", "AndroidManifest.xml");
1013+
FileAssert.Exists (manifestPath);
1014+
var manifest = XDocument.Load (manifestPath);
1015+
XNamespace ns = "http://schemas.android.com/apk/res/android";
1016+
Assert.AreEqual (minSdkVersion.ToString (), manifest.Root.Element ("uses-sdk").Attribute (ns + "minSdkVersion").Value);
1017+
}
1018+
9671019
}
9681020
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -806,36 +806,6 @@ public void DotNetBuild (string runtimeIdentifiers, bool isRelease, bool aot, bo
806806
}
807807
}
808808

809-
810-
// TODO: <uses-sdk android:minSdkVersion="32" android:targetSdkVersion="32" />
811-
// Causes warning: D8 : warning : An API level of 32 is not supported by this compiler. Please use an API level of 31 or earlier
812-
// Add a 32 parameter here when we get a newer version of r8.
813-
[Test]
814-
public void SupportedOSPlatformVersion ([Values (21, 31)] int minSdkVersion)
815-
{
816-
var proj = new XASdkProject {
817-
SupportedOSPlatformVersion = minSdkVersion.ToString (),
818-
};
819-
// Call AccessibilityTraversalAfter from API level 22
820-
// https://developer.android.com/reference/android/view/View#getAccessibilityTraversalAfter()
821-
proj.MainActivity = proj.DefaultMainActivity.Replace ("button!.Click", "button!.AccessibilityTraversalAfter.ToString ();\nbutton!.Click");
822-
823-
var dotnet = CreateDotNetBuilder (proj);
824-
Assert.IsTrue (dotnet.Build (), "`dotnet build` should succeed");
825-
826-
if (minSdkVersion < 22) {
827-
StringAssertEx.Contains ("warning CA1416", dotnet.LastBuildOutput, "Should get warning about Android 22 API");
828-
} else {
829-
dotnet.AssertHasNoWarnings ();
830-
}
831-
832-
var manifestPath = Path.Combine (FullProjectDirectory, proj.IntermediateOutputPath, "android", "AndroidManifest.xml");
833-
FileAssert.Exists (manifestPath);
834-
var manifest = XDocument.Load (manifestPath);
835-
XNamespace ns = "http://schemas.android.com/apk/res/android";
836-
Assert.AreEqual (minSdkVersion.ToString (), manifest.Root.Element ("uses-sdk").Attribute (ns + "minSdkVersion").Value);
837-
}
838-
839809
[Test]
840810
public void DotNetBuildXamarinForms ([Values (true, false)] bool useInterpreter)
841811
{

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XASdkProject.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ public XASdkProject (string outputType = "Exe", [CallerMemberName] string packag
7979
Sources.Add (new BuildItem.Source ($"Resources\\Resource.designer{Language.DefaultExtension}") { TextContent = () => string.Empty });
8080
}
8181

82-
protected override bool UseDotNet => true;
83-
8482
public string OutputPath => Path.Combine ("bin", Configuration, TargetFramework.ToLowerInvariant ());
8583

8684
public string IntermediateOutputPath => Path.Combine ("obj", Configuration, TargetFramework.ToLowerInvariant ());

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug"
5757
</Project>"
5858
});
5959
} else {
60+
MinSdkVersion = "19";
6061
SetProperty ("_FastDeploymentDiagnosticLogging", "True");
6162
SetProperty ("AndroidApplication", "True");
6263
SetProperty ("AndroidResgenClass", "Resource");
@@ -101,7 +102,16 @@ public virtual string DefaultMainActivity {
101102
/// <summary>
102103
/// Defaults to API 19
103104
/// </summary>
104-
public string MinSdkVersion { get; set; } = "19";
105+
[Obsolete ("Use SupportedOSPlatformVersion for .NET projects.")]
106+
public string MinSdkVersion { get; set; }
107+
108+
/// <summary>
109+
/// Defaults to 21.0
110+
/// </summary>
111+
public string SupportedOSPlatformVersion {
112+
get { return GetProperty (KnownProperties.SupportedOSPlatformVersion); }
113+
set { SetProperty (KnownProperties.SupportedOSPlatformVersion, value); }
114+
}
105115

106116
string AotAssembliesPropertyName => Builder.UseDotNet ? KnownProperties.RunAOTCompilation : KnownProperties.AotAssemblies;
107117

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetStandard.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ public string PackageTargetFallback {
3030
get { return GetProperty ("PackageTargetFallback"); }
3131
set { SetProperty ("PackageTargetFallback", value); }
3232
}
33-
public string TargetFramework {
34-
get { return GetProperty ("TargetFramework"); }
35-
set { SetProperty ("TargetFramework", value); }
36-
}
3733

3834
/// <summary>
3935
/// Projects targeting net7.0 require ref/runtime packs on NuGet.org or dotnet6/dotnet7

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetXamarinProject.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ protected DotNetXamarinProject (string debugConfigurationName = "Debug", string
2626
SetProperty ("AssemblyName", () => AssemblyName ?? ProjectName);
2727

2828
if (Builder.UseDotNet) {
29-
SetProperty ("TargetFramework", "net8.0-android");
30-
SetProperty ("EnableDefaultItems", "false");
31-
SetProperty ("AppendTargetFrameworkToOutputPath", "false");
29+
TargetFramework = "net8.0-android";
30+
EnableDefaultItems = false;
31+
AppendTargetFrameworkToOutputPath = false;
3232
} else {
3333
AddReferences ("System"); // default
3434
SetProperty ("Platform", "AnyCPU", "'$(Platform)' == ''");
@@ -77,7 +77,15 @@ public string IntermediateOutputPath {
7777

7878
public string Sdk { get; set; } = "Microsoft.NET.Sdk";
7979

80-
public bool EnableDefaultItems => false;
80+
public bool EnableDefaultItems {
81+
get { return string.Equals (GetProperty ("EnableDefaultItems"), "true", StringComparison.OrdinalIgnoreCase); }
82+
set { SetProperty ("EnableDefaultItems", value.ToString ()); }
83+
}
84+
85+
public bool AppendTargetFrameworkToOutputPath {
86+
get { return string.Equals (GetProperty ("AppendTargetFrameworkToOutputPath"), "true", StringComparison.OrdinalIgnoreCase); }
87+
set { SetProperty ("AppendTargetFrameworkToOutputPath", value.ToString ()); }
88+
}
8189

8290
public void AddReferences (params string [] references)
8391
{

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/XamarinProject.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public XamarinProject (string debugConfigurationName = "Debug", string releaseCo
8888
Packages = new List<Package> ();
8989
Imports = new List<Import> ();
9090

91-
if (UseDotNet) {
91+
if (Builder.UseDotNet) {
9292
//NOTE: for SDK-style projects, we need $(Configuration) set before Microsoft.NET.Sdk.targets
9393
Imports.Add (new Import ("Directory.Build.props") {
9494
TextContent = () =>
@@ -114,7 +114,10 @@ public void AddReference (XamarinProject other, string include = null)
114114
References.Add (new BuildItem.ProjectReference (include, other.ProjectName, other.ProjectGuid));
115115
}
116116

117-
protected virtual bool UseDotNet => Builder.UseDotNet;
117+
public string TargetFramework {
118+
get { return GetProperty ("TargetFramework"); }
119+
set { SetProperty ("TargetFramework", value); }
120+
}
118121

119122
public string GetProperty (string name)
120123
{

src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,14 +304,14 @@ public IList<string> Merge (TaskLoggingHelper log, TypeDefinitionCache cache, Li
304304
new XAttribute (androidNs + "targetSdkVersion", TargetSdkVersionName)));
305305
}
306306

307-
// If no minSdkVersion is specified, set it to TargetFrameworkVersion
307+
// If no minSdkVersion is specified, set it to XABuildConfig.NDKMinimumApiAvailable
308+
// For .NET projects, $(SupportedOSPlatformVersion) will be used.
308309
var uses = manifest.Element ("uses-sdk");
309310

310311
if (uses.Attribute (androidNs + "minSdkVersion") == null) {
311312
int minSdkVersion;
312313
if (!int.TryParse (MinSdkVersionName, out minSdkVersion))
313314
minSdkVersion = XABuildConfig.NDKMinimumApiAvailable;
314-
minSdkVersion = Math.Min (minSdkVersion, XABuildConfig.NDKMinimumApiAvailable);
315315
uses.SetAttributeValue (androidNs + "minSdkVersion", minSdkVersion.ToString ());
316316
}
317317

0 commit comments

Comments
 (0)