diff --git a/external/Java.Interop b/external/Java.Interop index ccafbe6a102..7a058c0ee50 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit ccafbe6a102a85efe84ceb210b3b8b93e49edbcb +Subproject commit 7a058c0ee50d39dc5783d2b2770ea5e0f1001a56 diff --git a/src/Mono.Android/Android.Runtime/JNIEnvInit.cs b/src/Mono.Android/Android.Runtime/JNIEnvInit.cs index 2b3bed66a3c..7ac2bdf2a39 100644 --- a/src/Mono.Android/Android.Runtime/JNIEnvInit.cs +++ b/src/Mono.Android/Android.Runtime/JNIEnvInit.cs @@ -50,7 +50,7 @@ internal struct JnienvInitializeArgs { internal static IntPtr java_class_loader; internal static JniMethodInfo? mid_Class_forName; - static AndroidRuntime? androidRuntime; + internal static AndroidRuntime? androidRuntime; [UnmanagedCallersOnly] static unsafe void RegisterJniNatives (IntPtr typeName_ptr, int typeName_len, IntPtr jniClass, IntPtr methods_ptr, int methods_len) diff --git a/src/Mono.Android/Java.Interop/TypeManager.cs b/src/Mono.Android/Java.Interop/TypeManager.cs index fb4e87216a4..606051530e9 100644 --- a/src/Mono.Android/Java.Interop/TypeManager.cs +++ b/src/Mono.Android/Java.Interop/TypeManager.cs @@ -267,7 +267,7 @@ internal static IJavaPeerable CreateInstance (IntPtr handle, JniHandleOwnership [UnconditionalSuppressMessage ("Trimming", "IL2067", Justification = "TypeManager.CreateProxy() does not statically know the value of the 'type' local variable.")] [UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "TypeManager.CreateProxy() does not statically know the value of the 'type' local variable.")] - internal static IJavaPeerable CreateInstance (IntPtr handle, JniHandleOwnership transfer, Type? targetType) + internal static IJavaPeerable? CreateInstance (IntPtr handle, JniHandleOwnership transfer, Type? targetType) { Type? type = null; IntPtr class_ptr = JNIEnv.GetObjectClass (handle); @@ -318,6 +318,26 @@ internal static IJavaPeerable CreateInstance (IntPtr handle, JniHandleOwnership type = invokerType; } + var typeSig = JNIEnvInit.androidRuntime?.TypeManager.GetTypeSignature (type) ?? default; + if (!typeSig.IsValid || typeSig.SimpleReference == null) { + throw new ArgumentException ($"Could not determine Java type corresponding to `{type.AssemblyQualifiedName}`.", nameof (targetType)); + } + JniObjectReference typeClass; + try { + typeClass = JniEnvironment.Types.FindClass (typeSig.SimpleReference); + } catch (Exception e) { + throw new ArgumentException ($"Could not find Java class `{typeSig.SimpleReference}`.", + nameof (targetType), + e); + } + + var handleClass = JniEnvironment.Types.GetObjectClass (new JniObjectReference (handle)); + if (!JniEnvironment.Types.IsAssignableFrom (handleClass, typeClass)) { + Logger.Log (LogLevel.Info, "*jonp*", $"# jonp: can't assign `{GetClassName(handleClass.Handle)}` to `{GetClassName(typeClass.Handle)}`"); + JniObjectReference.Dispose (ref handleClass); + JniObjectReference.Dispose (ref typeClass); + return null; + } IJavaPeerable? result = null; diff --git a/tests/Mono.Android-Tests/Java.Interop/JavaObjectExtensionsTests.cs b/tests/Mono.Android-Tests/Java.Interop/JavaObjectExtensionsTests.cs index d936393c032..e6b133a4eaf 100644 --- a/tests/Mono.Android-Tests/Java.Interop/JavaObjectExtensionsTests.cs +++ b/tests/Mono.Android-Tests/Java.Interop/JavaObjectExtensionsTests.cs @@ -56,6 +56,14 @@ public void JavaCast_CheckForManagedSubclasses () } } + [Test] + public void JavaAs () + { + using var v = new Java.InteropTests.MyJavaInterfaceImpl (); + using var c = v.JavaAs(); + Assert.IsNotNull (c); + } + static Java.Lang.Object CreateObject () { var ctor = JNIEnv.GetMethodID (Java.Lang.Class.Object, "", "()V");