Skip to content

Commit

Permalink
[XABT] Do not prefer NDKMinimumApiAvailable
Browse files Browse the repository at this point in the history
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)`.
  • Loading branch information
pjcollins committed May 10, 2023
1 parent fb10769 commit b70ed5f
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Xml.XPath;
using Xamarin.Tools.Zip;
using System.Collections.Generic;
using Xamarin.Android.Tools;

namespace Xamarin.Android.Build.Tests
{
Expand Down Expand Up @@ -964,5 +965,55 @@ public void ExportedErrorMessage ()
Assert.IsTrue (b.LastBuildOutput.ContainsText ($"AndroidManifest.xml(12,5): java{extension} error AMM0000:"), "Should recieve AMM0000 error");
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");
}

// TODO: <uses-sdk android:minSdkVersion="32" android:targetSdkVersion="32" />
// Causes warning: D8 : warning : An API level of 32 is not supported by this compiler. Please use an API level of 31 or earlier
// Add a 32 parameter here when we get a newer version of r8.
[Test]
[TestCase (0, true)]
[TestCase (0, false)]
[TestCase (21, true)]
[TestCase (31, false)]
public void SupportedOSPlatformVersion (int minSdkVersion, bool removeUsesSdkElement)
{
var proj = new XamarinAndroidApplicationProject {
EnableDefaultItems = true,
};

// Do not set project property and use default value when minSdkVersion = 0
if (minSdkVersion > 0) {
proj.SupportedOSPlatformVersion = minSdkVersion.ToString ();
} else {
minSdkVersion = XABuildConfig.AndroidDefaultTargetDotnetApiLevel;
}

if (removeUsesSdkElement) {
proj.AndroidManifest = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<manifest xmlns:android=""http://schemas.android.com/apk/res/android"" android:versionCode=""1"" android:versionName=""1.0"" package=""{proj.PackageName}"">
<application android:label=""{proj.ProjectName}"">
</application>
</manifest>";
}

// Call AccessibilityTraversalAfter from API level 22
// https://developer.android.com/reference/android/view/View#getAccessibilityTraversalAfter()
proj.MainActivity = proj.DefaultMainActivity.Replace ("button!.Click", "button!.AccessibilityTraversalAfter.ToString ();\nbutton!.Click");

var builder = CreateApkBuilder ();
Assert.IsTrue (builder.Build (proj), "`dotnet build` should succeed");

if (minSdkVersion < 22) {
StringAssertEx.Contains ("warning CA1416", builder.LastBuildOutput, "Should get warning about Android 22 API");
} else {
builder.AssertHasNoWarnings ();
}

var manifestPath = Path.Combine (Root, builder.ProjectDirectory, proj.IntermediateOutputPath, "android", "AndroidManifest.xml");
FileAssert.Exists (manifestPath);
var manifest = XDocument.Load (manifestPath);
XNamespace ns = "http://schemas.android.com/apk/res/android";
Assert.AreEqual (minSdkVersion.ToString (), manifest.Root.Element ("uses-sdk").Attribute (ns + "minSdkVersion").Value);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -806,36 +806,6 @@ public void DotNetBuild (string runtimeIdentifiers, bool isRelease, bool aot, bo
}
}


// TODO: <uses-sdk android:minSdkVersion="32" android:targetSdkVersion="32" />
// Causes warning: D8 : warning : An API level of 32 is not supported by this compiler. Please use an API level of 31 or earlier
// Add a 32 parameter here when we get a newer version of r8.
[Test]
public void SupportedOSPlatformVersion ([Values (21, 31)] int minSdkVersion)
{
var proj = new XASdkProject {
SupportedOSPlatformVersion = minSdkVersion.ToString (),
};
// Call AccessibilityTraversalAfter from API level 22
// https://developer.android.com/reference/android/view/View#getAccessibilityTraversalAfter()
proj.MainActivity = proj.DefaultMainActivity.Replace ("button!.Click", "button!.AccessibilityTraversalAfter.ToString ();\nbutton!.Click");

var dotnet = CreateDotNetBuilder (proj);
Assert.IsTrue (dotnet.Build (), "`dotnet build` should succeed");

if (minSdkVersion < 22) {
StringAssertEx.Contains ("warning CA1416", dotnet.LastBuildOutput, "Should get warning about Android 22 API");
} else {
dotnet.AssertHasNoWarnings ();
}

var manifestPath = Path.Combine (FullProjectDirectory, proj.IntermediateOutputPath, "android", "AndroidManifest.xml");
FileAssert.Exists (manifestPath);
var manifest = XDocument.Load (manifestPath);
XNamespace ns = "http://schemas.android.com/apk/res/android";
Assert.AreEqual (minSdkVersion.ToString (), manifest.Root.Element ("uses-sdk").Attribute (ns + "minSdkVersion").Value);
}

[Test]
public void DotNetBuildXamarinForms ([Values (true, false)] bool useInterpreter)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ public XASdkProject (string outputType = "Exe", [CallerMemberName] string packag
Sources.Add (new BuildItem.Source ($"Resources\\Resource.designer{Language.DefaultExtension}") { TextContent = () => string.Empty });
}

protected override bool UseDotNet => true;

public string OutputPath => Path.Combine ("bin", Configuration, TargetFramework.ToLowerInvariant ());

public string IntermediateOutputPath => Path.Combine ("obj", Configuration, TargetFramework.ToLowerInvariant ());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug"
</Project>"
});
} else {
MinSdkVersion = "19";
SetProperty ("_FastDeploymentDiagnosticLogging", "True");
SetProperty ("AndroidApplication", "True");
SetProperty ("AndroidResgenClass", "Resource");
Expand Down Expand Up @@ -101,7 +102,16 @@ public virtual string DefaultMainActivity {
/// <summary>
/// Defaults to API 19
/// </summary>
public string MinSdkVersion { get; set; } = "19";
[Obsolete ("Use SupportedOSPlatformVersion for .NET projects.")]
public string MinSdkVersion { get; set; }

/// <summary>
/// Defaults to 21.0
/// </summary>
public string SupportedOSPlatformVersion {
get { return GetProperty (KnownProperties.SupportedOSPlatformVersion); }
set { SetProperty (KnownProperties.SupportedOSPlatformVersion, value); }
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ public string PackageTargetFallback {
get { return GetProperty ("PackageTargetFallback"); }
set { SetProperty ("PackageTargetFallback", value); }
}
public string TargetFramework {
get { return GetProperty ("TargetFramework"); }
set { SetProperty ("TargetFramework", value); }
}

/// <summary>
/// Projects targeting net7.0 require ref/runtime packs on NuGet.org or dotnet6/dotnet7
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ protected DotNetXamarinProject (string debugConfigurationName = "Debug", string
SetProperty ("AssemblyName", () => AssemblyName ?? ProjectName);

if (Builder.UseDotNet) {
SetProperty ("TargetFramework", "net8.0-android");
SetProperty ("EnableDefaultItems", "false");
SetProperty ("AppendTargetFrameworkToOutputPath", "false");
TargetFramework = "net8.0-android";
EnableDefaultItems = false;
AppendTargetFrameworkToOutputPath = false;
} else {
AddReferences ("System"); // default
SetProperty ("Platform", "AnyCPU", "'$(Platform)' == ''");
Expand Down Expand Up @@ -77,7 +77,15 @@ public string IntermediateOutputPath {

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

public bool EnableDefaultItems => false;
public bool EnableDefaultItems {
get { return string.Equals (GetProperty ("EnableDefaultItems"), "true", StringComparison.OrdinalIgnoreCase); }
set { SetProperty ("EnableDefaultItems", value.ToString ()); }
}

public bool AppendTargetFrameworkToOutputPath {
get { return string.Equals (GetProperty ("AppendTargetFrameworkToOutputPath"), "true", StringComparison.OrdinalIgnoreCase); }
set { SetProperty ("AppendTargetFrameworkToOutputPath", value.ToString ()); }
}

public void AddReferences (params string [] references)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public XamarinProject (string debugConfigurationName = "Debug", string releaseCo
Packages = new List<Package> ();
Imports = new List<Import> ();

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

protected virtual bool UseDotNet => Builder.UseDotNet;
public string TargetFramework {
get { return GetProperty ("TargetFramework"); }
set { SetProperty ("TargetFramework", value); }
}

public string GetProperty (string name)
{
Expand Down
4 changes: 2 additions & 2 deletions src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -304,14 +304,14 @@ public IList<string> Merge (TaskLoggingHelper log, TypeDefinitionCache cache, Li
new XAttribute (androidNs + "targetSdkVersion", TargetSdkVersionName)));
}

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

if (uses.Attribute (androidNs + "minSdkVersion") == null) {
int minSdkVersion;
if (!int.TryParse (MinSdkVersionName, out minSdkVersion))
minSdkVersion = XABuildConfig.NDKMinimumApiAvailable;
minSdkVersion = Math.Min (minSdkVersion, XABuildConfig.NDKMinimumApiAvailable);
uses.SetAttributeValue (androidNs + "minSdkVersion", minSdkVersion.ToString ());
}

Expand Down

0 comments on commit b70ed5f

Please sign in to comment.