Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Configuration.props
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
<TargetFrameworkVersion Condition=" '$(TargetFrameworkVersion)' == '' And '$(UsingMicrosoftNETSdk)' != 'true' ">v4.7.1</TargetFrameworkVersion>
<!-- Used by the `build-tools/create-vsix` build so that `Mono.Android.Export.dll`/etc. are only included *once* -->
<!-- Should correspond to the first value from `$(API_LEVELS)` in `build-tools/api-xml-adjuster/Makefile` -->
<AndroidFirstFrameworkVersion Condition="'$(AndroidFirstFrameworkVersion)' == ''">v4.4</AndroidFirstFrameworkVersion>
<AndroidFirstApiLevel Condition="'$(AndroidFirstApiLevel)' == ''">19</AndroidFirstApiLevel>
<AndroidFirstFrameworkVersion Condition="'$(AndroidFirstFrameworkVersion)' == ''">v5.0</AndroidFirstFrameworkVersion>
<AndroidFirstApiLevel Condition="'$(AndroidFirstApiLevel)' == ''">21</AndroidFirstApiLevel>
<AndroidFirstPlatformId Condition="'$(AndroidFirstPlatformId)' == ''">$(AndroidFirstApiLevel)</AndroidFirstPlatformId>
<_IsRunningNuGetRestore Condition="$(RestoreTaskAssemblyFile.EndsWith('NuGet.exe', StringComparison.InvariantCultureIgnoreCase))">True</_IsRunningNuGetRestore>
<!-- *Latest* *stable* API level binding that we support; used when building src/Xamarin.Android.Build.Tasks -->
Expand Down Expand Up @@ -136,8 +136,8 @@
<AndroidToolPath Condition=" '$(AndroidToolPath)' == '' ">$(AndroidSdkFullPath)\tools</AndroidToolPath>
<AndroidToolsBinPath Condition=" '$(AndroidToolsBinPath)' == '' ">$(AndroidToolPath)\bin</AndroidToolsBinPath>
<AndroidToolExe Condition=" '$(AndroidToolExe)' == '' ">android</AndroidToolExe>
<EmulatorVersion Condition=" '$(EmulatorVersion)' == '' ">5598178</EmulatorVersion>
<EmulatorPkgRevision Condition=" '$(EmulatorPkgRevision)' == '' ">29.0.11</EmulatorPkgRevision>
<EmulatorVersion Condition=" '$(EmulatorVersion)' == '' ">6306047</EmulatorVersion>
<EmulatorPkgRevision Condition=" '$(EmulatorPkgRevision)' == '' ">30.0.5</EmulatorPkgRevision>
<EmulatorToolPath Condition=" '$(EmulatorToolPath)' == '' ">$(AndroidSdkFullPath)\emulator</EmulatorToolPath>
<EmulatorToolExe Condition=" '$(EmulatorToolExe)' == '' ">emulator</EmulatorToolExe>
<NdkBuildPath Condition=" '$(NdkBuildPath)' == '' And '$(HostOS)' != 'Windows' ">$(AndroidNdkDirectory)\ndk-build</NdkBuildPath>
Expand Down
16 changes: 16 additions & 0 deletions Documentation/release-notes/4584.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
### Minimum compatible Android version now Android 5.0 Lollipop (API level 21)

The minimum compatible Android version for Xamarin.Android apps is now Android
5.0 Lollipop (API level 21). Warning XA4216 has been updated to help highlight
this change for any projects that might still have an older version set for the
`minSdkVersion` in the `AndroidManifest.xml` file:

```
warning XA4216: AndroidManifest.xml //uses-sdk/@android:minSdkVersion '20' is less than API-21, this configuration is not supported.
```

#### Background information

The unmanaged native libraries that are part of Xamarin.Android are now built to
target Android 5.0 Lollipop (API level 21), so apps built using this release can
abort due to incompatible APIs if run on earlier Android versions.
2 changes: 0 additions & 2 deletions build-tools/api-merge/merge-configuration.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
<File Path="api-R.xml.in" Level="R" />
</Inputs>
<Outputs>
<File Path="android-19\mcw\api.xml" LastLevel="19" />
<File Path="android-20\mcw\api.xml" LastLevel="20" />
<File Path="android-21\mcw\api.xml" LastLevel="21" />
<File Path="android-22\mcw\api.xml" LastLevel="22" />
<File Path="android-23\mcw\api.xml" LastLevel="23" />
Expand Down
2 changes: 1 addition & 1 deletion build-tools/api-xml-adjuster/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ API_XML_TOOL = $(BUILDBIN)/api-xml-adjuster.exe
RUNTIME = mono --debug
RUN_CLASS_PARSE = $(RUNTIME) $(CLASS_PARSE)
RUN_API_XML_TOOL = $(RUNTIME) $(API_XML_TOOL)
API_LEVELS = 10 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 R
API_LEVELS = 21 22 23 24 25 26 27 28 29 R

XML_OUTPUT_DIR = .

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ namespace Xamarin.Android.Prepare
{
class BuildAndroidPlatforms
{
public const string AndroidNdkVersion = "21";
public const string AndroidNdkPkgRevision = "21.0.6113669";
public const string AndroidNdkVersion = "21b";
public const string AndroidNdkPkgRevision = "21.1.6352462";

public static readonly List<AndroidPlatform> AllPlatforms = new List<AndroidPlatform> {
new AndroidPlatform (apiName: "", apiLevel: 1, platformID: "1"),
Expand All @@ -27,8 +27,8 @@ class BuildAndroidPlatforms
new AndroidPlatform (apiName: "Jelly Bean", apiLevel: 16, platformID: "16", include: "v4.1"),
new AndroidPlatform (apiName: "Jelly Bean", apiLevel: 17, platformID: "17", include: "v4.2"),
new AndroidPlatform (apiName: "Jelly Bean", apiLevel: 18, platformID: "18", include: "v4.3"),
new AndroidPlatform (apiName: "Kit Kat", apiLevel: 19, platformID: "19", include: "v4.4", framework: "v4.4"),
new AndroidPlatform (apiName: "Kit Kat + Wear support", apiLevel: 20, platformID: "20", include: "v4.4.87", framework: "v4.4.87"),
new AndroidPlatform (apiName: "Kit Kat", apiLevel: 19, platformID: "19", include: "v4.4"),
new AndroidPlatform (apiName: "Kit Kat + Wear support", apiLevel: 20, platformID: "20", include: "v4.4.87"),
new AndroidPlatform (apiName: "Lollipop", apiLevel: 21, platformID: "21", include: "v5.0", framework: "v5.0"),
new AndroidPlatform (apiName: "Lollipop", apiLevel: 22, platformID: "22", include: "v5.1", framework: "v5.1"),
new AndroidPlatform (apiName: "Marshmallow", apiLevel: 23, platformID: "23", include: "v6.0", framework: "v6.0"),
Expand All @@ -42,9 +42,9 @@ class BuildAndroidPlatforms
};

public static readonly Dictionary<string, uint> NdkMinimumAPI = new Dictionary<string, uint> {
{ AbiNames.TargetJit.AndroidArmV7a, 16 },
{ AbiNames.TargetJit.AndroidArmV7a, 21 },
{ AbiNames.TargetJit.AndroidArmV8a, 21 },
{ AbiNames.TargetJit.AndroidX86, 16 },
{ AbiNames.TargetJit.AndroidX86, 21 },
{ AbiNames.TargetJit.AndroidX86_64, 21 },
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ public AndroidToolchain ()

new AndroidToolchainComponent ("docs-24_r01", destDir: "docs", pkgRevision: "1"),
new AndroidToolchainComponent ("android_m2repository_r47", destDir: Path.Combine ("extras", "android", "m2repository"), pkgRevision: "47.0.0"),
new AndroidToolchainComponent ("x86-29_r06", destDir: Path.Combine ("system-images", "android-29", "default", "x86"), relativeUrl: new Uri ("sys-img/android/", UriKind.Relative), pkgRevision: "6"),

// NOTE: for some reason x86-29_r07 and x86_64-29_r07 zips are tagged with the OS name, JUST these system images - when
// updating to a latter version check if that's changed or not.
new AndroidToolchainComponent ($"x86_64-29_r07-{osTag}", destDir: Path.Combine ("system-images", "android-29", "default", "x86_64"), relativeUrl: new Uri ("sys-img/android/", UriKind.Relative), pkgRevision: "7"),
new AndroidToolchainComponent ($"x86-29_r07-{osTag}", destDir: Path.Combine ("system-images", "android-29", "default", "x86"), relativeUrl: new Uri ("sys-img/android/", UriKind.Relative), pkgRevision: "7"),
new AndroidToolchainComponent ($"android-ndk-r{AndroidNdkVersion}-{osTag}-x86_64", destDir: AndroidNdkDirectory, pkgRevision: AndroidPkgRevision),
new AndroidToolchainComponent ($"build-tools_r{XABuildToolsVersion}-{altOsTag}", destDir: Path.Combine ("build-tools", XABuildToolsFolder), isMultiVersion: true),
new AndroidToolchainComponent ($"platform-tools_r{XAPlatformToolsVersion}-{osTag}", destDir: "platform-tools", pkgRevision: XAPlatformToolsVersion),
Expand Down
9 changes: 8 additions & 1 deletion build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,17 @@ GeneratedFile Get_XABuildConfig_cs (Context context)
{
const string OutputFileName = "XABuildConfig.cs";

uint minimumApiAvailable = UInt32.MaxValue;
foreach (uint api in BuildAndroidPlatforms.NdkMinimumAPI.Values) {
if (api > minimumApiAvailable)
continue;
minimumApiAvailable = api;
}

var replacements = new Dictionary<string, string> (StringComparer.Ordinal) {
{ "@NDK_REVISION@", context.BuildInfo.NDKRevision },
{ "@NDK_RELEASE@", BuildAndroidPlatforms.AndroidNdkVersion },
{ "@NDK_MINIMUM_API_AVAILABLE@", context.BuildInfo.NDKMinimumApiAvailable },
{ "@NDK_MINIMUM_API_AVAILABLE@", minimumApiAvailable.ToString () },
{ "@NDK_VERSION_MAJOR@", context.BuildInfo.NDKVersionMajor },
{ "@NDK_VERSION_MINOR@", context.BuildInfo.NDKVersionMinor },
{ "@NDK_VERSION_MICRO@", context.BuildInfo.NDKVersionMicro },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,7 @@ public void BuildAotApplicationAndÜmläüts (string supportedAbis, bool enableL
// LLVM passes a direct path to libc.so, and we need to use the libc.so
// which corresponds to the *minimum* SDK version specified in AndroidManifest.xml
// Since we overrode minSdkVersion=16, that means we should use libc.so from android-16.
StringAssertEx.ContainsRegex (@"\s*\[aot-compiler stdout].*android-16.arch-.*.usr.lib.libc\.so", b.LastBuildOutput, "AOT+LLVM should use libc.so from minSdkVersion!");
StringAssertEx.ContainsRegex (@"\s*\[aot-compiler stdout].*android-21.arch-.*.usr.lib.libc\.so", b.LastBuildOutput, "AOT+LLVM should use libc.so from minSdkVersion!");
}
foreach (var abi in supportedAbis.Split (new char [] { ';' })) {
var libapp = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath,
Expand Down Expand Up @@ -1137,25 +1137,32 @@ public void BuildProguardEnabledProject ([Values (true, false)] bool isRelease,

XamarinAndroidApplicationProject CreateMultiDexRequiredApplication (string debugConfigurationName = "Debug", string releaseConfigurationName = "Release")
{
const int NumberOfMethods = (32 * 1024) - 1;
var proj = new XamarinAndroidApplicationProject (debugConfigurationName, releaseConfigurationName);
proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods.java") {
TextContent = () => "public class ManyMethods { \n"
+ string.Join (Environment.NewLine, Enumerable.Range (0, 32768).Select (i => "public void method" + i + "() {}"))
+ string.Join (Environment.NewLine, Enumerable.Range (0, NumberOfMethods).Select (i => "public void method" + i + "() {}"))
+ "}",
Encoding = Encoding.ASCII
});
proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods2.java") {
TextContent = () => "public class ManyMethods2 { \n"
+ string.Join (Environment.NewLine, Enumerable.Range (0, 32768).Select (i => "public void method" + i + "() {}"))
+ string.Join (Environment.NewLine, Enumerable.Range (0, NumberOfMethods).Select (i => "public void method" + i + "() {}"))
+ "}",
Encoding = Encoding.ASCII
});
proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods3.java") {
TextContent = () => "public class ManyMethods3 { \n"
+ string.Join (Environment.NewLine, Enumerable.Range (0, NumberOfMethods).Select (i => "public void method" + i + "() {}"))
+ "}",
Encoding = Encoding.ASCII
});
return proj;
}

[Test]
[Category ("Minor")]
public void BuildApplicationOver65536Methods ([Values ("dx", "d8")] string dexTool)
public void BuildApplicationRequiresMultiDex ([Values ("dx", "d8")] string dexTool)
{
var proj = CreateMultiDexRequiredApplication ();
proj.DexTool = dexTool;
Expand Down Expand Up @@ -1197,9 +1204,13 @@ public void BuildMultiDexApplication (bool useJackAndJill, string fxVersion)
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
Assert.IsTrue (File.Exists (Path.Combine (Root, b.ProjectDirectory, intermediateDir, "android/bin/classes.dex")),
"multidex-ed classes.zip exists");
var multidexKeepPath = Path.Combine (Root, b.ProjectDirectory, intermediateDir, "multidex.keep");
Assert.IsTrue (File.Exists (multidexKeepPath), "multidex.keep exists");
Assert.IsTrue (File.ReadAllLines (multidexKeepPath).Length > 1, "multidex.keep must contain more than one line.");

if (proj.DexTool != "d8") {
var multidexKeepPath = Path.Combine (Root, b.ProjectDirectory, intermediateDir, "multidex.keep");
Assert.IsTrue (File.Exists (multidexKeepPath), "multidex.keep exists");
Assert.IsTrue (File.ReadAllLines (multidexKeepPath).Length > 1, "multidex.keep must contain more than one line.");
}

Assert.IsTrue (b.LastBuildOutput.ContainsText (Path.Combine (proj.TargetFrameworkVersion, "mono.android.jar")), proj.TargetFrameworkVersion + "/mono.android.jar should be used.");
Assert.IsFalse (b.LastBuildOutput.ContainsText ("Duplicate zip entry"), "Should not get warning about [META-INF/MANIFEST.MF]");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ public void DirectBootAwareAttribute ()
}
}

// Information about version codes: https://devblogs.microsoft.com/xamarin/advanced-android-versioncode/
static object [] VersionCodeTestSource = new object [] {
new object[] {
/* seperateApk */ false,
Expand Down Expand Up @@ -362,7 +363,7 @@ public void DirectBootAwareAttribute ()
/* pattern */ "{abi}{minSDK:00}{versionCode:000}",
/* props */ null,
/* shouldBuild */ true,
/* expected */ "216012;316012",
/* expected */ "221012;321012",
},
new object[] {
/* seperateApk */ true,
Expand All @@ -372,7 +373,7 @@ public void DirectBootAwareAttribute ()
/* pattern */ "{abi}{minSDK:00}{screen}{versionCode:000}",
/* props */ "screen=24",
/* shouldBuild */ true,
/* expected */ "21624012;31624012",
/* expected */ "22124012;32124012",
},
new object[] {
/* seperateApk */ true,
Expand All @@ -382,7 +383,7 @@ public void DirectBootAwareAttribute ()
/* pattern */ "{abi}{minSDK:00}{screen}{foo:0}{versionCode:000}",
/* props */ "screen=24;foo=$(Foo)",
/* shouldBuild */ true,
/* expected */ "216241012;316241012",
/* expected */ "221241012;321241012",
},
new object[] {
/* seperateApk */ true,
Expand All @@ -392,7 +393,7 @@ public void DirectBootAwareAttribute ()
/* pattern */ "{abi}{minSDK:00}{screen}{foo:00}{versionCode:000}",
/* props */ "screen=24;foo=$(Foo)",
/* shouldBuild */ false,
/* expected */ "2162401012;3162401012",
/* expected */ "2212401012;3212401012",
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void TestNdkUtil ()
Assert.IsTrue (NdkUtil.ValidateNdkPlatform (log, ndkDir, arch, enableLLVM: false));
Assert.AreEqual (0, errors.Count, "NdkUtil.ValidateNdkPlatform should not have returned false.");
int level = NdkUtil.GetMinimumApiLevelFor (arch, ndkDir);
int expected = 16;
int expected = 21;
Assert.AreEqual (expected, level, $"Min Api Level for {arch} should be {expected}.");
var compilerNoQuotes = NdkUtil.GetNdkTool (ndkDir, arch, "gcc", level);
Assert.AreEqual (0, errors.Count, "NdkUtil.GetNdkTool should not have errored.");
Expand Down
6 changes: 3 additions & 3 deletions src/monodroid/jni/embedded-assemblies.cc
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ EmbeddedAssemblies::typemap_read_header ([[maybe_unused]] int dir_fd, const char
struct stat sbuf;
int res;

#if __ANDROID_API__ < 21
#if defined (WINDOWS)
simple_pointer_guard<char[]> full_file_path = utils.path_combine (dir_path, file_path);
res = stat (full_file_path, &sbuf);
#else
Expand All @@ -600,7 +600,7 @@ EmbeddedAssemblies::typemap_read_header ([[maybe_unused]] int dir_fd, const char
return false;
}

#if __ANDROID_API__ < 21
#if defined (WINDOWS)
fd = open (full_file_path, O_RDONLY);
#else
fd = openat (dir_fd, file_path, O_RDONLY);
Expand Down Expand Up @@ -800,7 +800,7 @@ EmbeddedAssemblies::try_load_typemaps_from_directory (const char *path)
}

int dir_fd;
#if __ANDROID_API__ < 21
#if WINDOWS
dir_fd = -1;
#else
dir_fd = dirfd (dir);
Expand Down