diff --git a/samples/NativeAOT/MainActivity.cs b/samples/NativeAOT/MainActivity.cs
index aaedc0aef2d..3550139e1b5 100644
--- a/samples/NativeAOT/MainActivity.cs
+++ b/samples/NativeAOT/MainActivity.cs
@@ -1,3 +1,4 @@
+using Android.Content.Res;
using Android.Runtime;
using Android.Util;
using System.Reflection;
@@ -17,5 +18,9 @@ protected override void OnCreate(Bundle? savedInstanceState)
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
+
+ // An example of an Android API that uses a Java array
+ var list = new ColorStateList (new int[][] { [ 0, 1 ]}, [0, 1]);
+ Log.Debug ("NativeAOT", "MainActivity.OnCreate() ColorStateList: " + list);
}
}
\ No newline at end of file
diff --git a/src/Mono.Android/Android.App/SyncContext.cs b/src/Mono.Android/Android.App/SyncContext.cs
index 6c3daa83c7d..4d15f773606 100644
--- a/src/Mono.Android/Android.App/SyncContext.cs
+++ b/src/Mono.Android/Android.App/SyncContext.cs
@@ -18,8 +18,6 @@ static bool EnsureLooper ([NotNullWhen (true)]Looper? looper, SendOrPostCallback
{
if (looper == null) {
var message = $"No Android message loop is available. Skipping invocation of `{d.Method.DeclaringType?.FullName}.{d.Method.Name}`!";
- if (JNIEnvInit.IsRunningOnDesktop)
- message += " Using `await` when running on the Android Designer is not currently supported. Please use the `View.IsInEditMode` property.";
Logger.Log (LogLevel.Error, "monodroid-synccontext", message);
return false;
}
diff --git a/src/Mono.Android/Android.Runtime/AndroidRuntime.cs b/src/Mono.Android/Android.Runtime/AndroidRuntime.cs
index abf30a6ef4b..2abf1d9247a 100644
--- a/src/Mono.Android/Android.Runtime/AndroidRuntime.cs
+++ b/src/Mono.Android/Android.Runtime/AndroidRuntime.cs
@@ -278,23 +278,22 @@ protected override IEnumerable GetTypesForSimpleReference (string jniSimpl
protected override string? GetSimpleReference (Type type)
{
+ if (RuntimeFeature.UseReflectionForManagedToJava) {
+ return JavaNativeTypeManager.ToJniName (type);
+ }
string? j = JNIEnv.TypemapManagedToJava (type);
if (j != null) {
return GetReplacementTypeCore (j) ?? j;
}
- if (JNIEnvInit.IsRunningOnDesktop) {
- return JavaNativeTypeManager.ToJniName (type);
- }
return null;
}
protected override IEnumerable GetSimpleReferences (Type type)
{
- string? j = JNIEnv.TypemapManagedToJava (type);
- j = GetReplacementTypeCore (j) ?? j;
-
- if (JNIEnvInit.IsRunningOnDesktop) {
+ string? j;
+ if (RuntimeFeature.UseReflectionForManagedToJava) {
string? d = JavaNativeTypeManager.ToJniName (type);
+ j = GetReplacementTypeCore (d);
if (j != null && d != null) {
return new[]{j, d};
}
@@ -302,6 +301,9 @@ protected override IEnumerable GetSimpleReferences (Type type)
return new[]{d};
}
}
+
+ j = JNIEnv.TypemapManagedToJava (type);
+ j = GetReplacementTypeCore (j) ?? j;
if (j != null) {
return new[]{j};
}
diff --git a/src/Mono.Android/Android.Runtime/JNIEnv.cs b/src/Mono.Android/Android.Runtime/JNIEnv.cs
index 9cf5207f6af..afb6c4e7dc9 100644
--- a/src/Mono.Android/Android.Runtime/JNIEnv.cs
+++ b/src/Mono.Android/Android.Runtime/JNIEnv.cs
@@ -446,6 +446,9 @@ public static string GetJniName (Type type)
if (type == null)
throw new ArgumentNullException ("type");
+ if (RuntimeFeature.UseReflectionForManagedToJava)
+ return JavaNativeTypeManager.ToJniName (type);
+
string? java = TypemapManagedToJava (type);
return java == null
? JavaNativeTypeManager.ToJniName (type)
diff --git a/src/Mono.Android/Android.Runtime/JNIEnvInit.cs b/src/Mono.Android/Android.Runtime/JNIEnvInit.cs
index 2499b693cf2..504e7ade4f5 100644
--- a/src/Mono.Android/Android.Runtime/JNIEnvInit.cs
+++ b/src/Mono.Android/Android.Runtime/JNIEnvInit.cs
@@ -24,7 +24,6 @@ internal struct JnienvInitializeArgs {
public int version; // TODO: remove, not needed anymore
public int grefGcThreshold;
public IntPtr grefIGCUserPeer;
- public int isRunningOnDesktop;
public byte brokenExceptionTransitions;
public int packageNamingPolicy;
public byte ioExceptionType;
@@ -36,7 +35,6 @@ internal struct JnienvInitializeArgs {
#pragma warning restore 0649
internal static JniRuntime.JniValueManager? ValueManager;
- internal static bool IsRunningOnDesktop;
internal static bool jniRemappingInUse;
internal static bool MarshalMethodsEnabled;
internal static bool PropagateExceptions;
@@ -102,21 +100,12 @@ internal static unsafe void Initialize (JnienvInitializeArgs* args)
androidRuntime = new AndroidRuntime (args->env, args->javaVm, args->grefLoader, args->Loader_loadClass, args->jniAddNativeMethodRegistrationAttributePresent != 0);
ValueManager = androidRuntime.ValueManager;
- IsRunningOnDesktop = args->isRunningOnDesktop == 1;
-
grefIGCUserPeer_class = args->grefIGCUserPeer;
grefGCUserPeerable_class = args->grefGCUserPeerable;
PropagateExceptions = args->brokenExceptionTransitions == 0;
JavaNativeTypeManager.PackageNamingPolicy = (PackageNamingPolicy)args->packageNamingPolicy;
- if (IsRunningOnDesktop) {
- var packageNamingPolicy = Environment.GetEnvironmentVariable ("__XA_PACKAGE_NAMING_POLICY__");
- if (Enum.TryParse (packageNamingPolicy, out PackageNamingPolicy pnp)) {
- JavaNativeTypeManager.PackageNamingPolicy = pnp;
- }
- }
-
SetSynchronizationContext ();
}
diff --git a/src/Mono.Android/Android.Runtime/RuntimeFeature.cs b/src/Mono.Android/Android.Runtime/RuntimeFeature.cs
new file mode 100644
index 00000000000..a62d23310ec
--- /dev/null
+++ b/src/Mono.Android/Android.Runtime/RuntimeFeature.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Android.Runtime;
+
+static class RuntimeFeature
+{
+ const string FeatureSwitchPrefix = "Android.Runtime.RuntimeFeature.";
+
+ [FeatureSwitchDefinition ($"{FeatureSwitchPrefix}{nameof (UseReflectionForManagedToJava)}")]
+ internal static bool UseReflectionForManagedToJava { get; } =
+ AppContext.TryGetSwitch ($"{FeatureSwitchPrefix}{nameof (UseReflectionForManagedToJava)}", out bool isEnabled) ? isEnabled : false;
+}
diff --git a/src/Mono.Android/ILLink/ILLink.Substitutions.xml b/src/Mono.Android/ILLink/ILLink.Substitutions.xml
index 80459d1cd60..f1617bad66f 100644
--- a/src/Mono.Android/ILLink/ILLink.Substitutions.xml
+++ b/src/Mono.Android/ILLink/ILLink.Substitutions.xml
@@ -4,5 +4,9 @@
+
+
+
+
diff --git a/src/Mono.Android/Java.Interop/TypeManager.cs b/src/Mono.Android/Java.Interop/TypeManager.cs
index 8b775aea7db..b7839867a1d 100644
--- a/src/Mono.Android/Java.Interop/TypeManager.cs
+++ b/src/Mono.Android/Java.Interop/TypeManager.cs
@@ -221,12 +221,10 @@ static Exception CreateJavaLocationException ()
if (type != null)
return type;
- if (!JNIEnvInit.IsRunningOnDesktop) {
- // Miss message is logged in the native runtime
- if (Logger.LogAssembly)
- JNIEnv.LogTypemapTrace (new System.Diagnostics.StackTrace (true));
- return null;
- }
+ // Miss message is logged in the native runtime
+ if (Logger.LogAssembly)
+ JNIEnv.LogTypemapTrace (new System.Diagnostics.StackTrace (true));
+ return null;
return null;
}
@@ -368,7 +366,7 @@ public static void RegisterType (string java_class, Type t)
if (String.Compare (jniFromType, java_class, StringComparison.OrdinalIgnoreCase) != 0) {
TypeManagerMapDictionaries.ManagedToJni.Add (t, java_class);
}
- } else if (!JNIEnvInit.IsRunningOnDesktop || t != typeof (Java.Interop.TypeManager)) {
+ } else if (t != typeof (Java.Interop.TypeManager)) {
// skip the registration and output a warning
Logger.Log (LogLevel.Warn, "monodroid", FormattableString.Invariant ($"Type Registration Skipped for {java_class} to {t} "));
}
diff --git a/src/Mono.Android/Mono.Android.csproj b/src/Mono.Android/Mono.Android.csproj
index 6c409057f53..9aea5e4840c 100644
--- a/src/Mono.Android/Mono.Android.csproj
+++ b/src/Mono.Android/Mono.Android.csproj
@@ -258,6 +258,7 @@
+
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
index 0735371eacc..473c9399a54 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
@@ -13,6 +13,7 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
<_AndroidRuntimePackRuntime>NativeAOT
JavaInterop1
+ <_AndroidUseReflectionForManagedToJava Condition=" '$(_AndroidUseReflectionForManagedToJava)' == '' ">true
true
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.RuntimeConfig.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.RuntimeConfig.targets
index 899156a5b4e..506b343dbb1 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.RuntimeConfig.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.RuntimeConfig.targets
@@ -46,6 +46,10 @@ See: https://github.com/dotnet/runtime/blob/b13715b6984889a709ba29ea8a1961db469f
Value="$(AndroidAvoidEmitForPerformance)"
Trim="true"
/>
+
GetVersion ();
- init.isRunningOnDesktop = is_running_on_desktop ? 1 : 0;
init.brokenExceptionTransitions = application_config.broken_exception_transitions ? 1 : 0;
init.packageNamingPolicy = static_cast(application_config.package_naming_policy);
init.boundExceptionType = application_config.bound_exception_type;