You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Android.Runtime] Use JniTypeManager to register natives (#1550)
The new code uses `JniTypeManager`'s `RegisterNativeMembers()` method
to register native marshaling methods. The type manager itself uses
the register method generated by the `jnimarshalmethod-gen.exe` tool
or method(s) on the given type, which have the
`[Java.Interop.JniAddNativeMethodRegistrationAttribute]`
custom attribute.
When no such `__<$>_jni_marshal_methods.__RegisterNativeMembers()`
method exists, we fallback to the original (old) code.
Example register class generated by `jnimarshalmethod-gen.exe`:
partial class MainActivity {
partial class '__<$>_jni_marshal_methods' {
[JniAddNativeMethodRegistration]
public static void __RegisterNativeMembers (JniNativeMethodRegistrationArguments args)
{
args.AddRegistrations (new JniNativeMethodRegistration[] {
new JniNativeMethodRegistration (
"n_onCreate",
"(Landroid/os/Bundle;)V",
new Action<IntPtr, IntPtr, IntPtr> (MainActivity.__<$>_jni_marshal_methods.n_onCreate_Landroid_os_Bundle_))
});
}
public static void n_onCreate_Landroid_os_Bundle_ (IntPtr __jnienv, IntPtr __this, IntPtr bundle)
{
var __envp = new JniTransition (__this);
JniRuntime __jvm;
try {
__jvm = JniEnvironment.Runtime;
__jvm.ValueManager.WaitForGCBridgeProcessing();
var __this_val = __jvm.ValueManager.GetValue<MainActivity>(__this);
var __bundle_val = __jvm.ValueManager.GetValue<Bundle>(bundle);
__this_val.OnCreate (__bundle_val);
}
catch (Exception __e) if (__jvm.ExceptionShouldTransitionToJni(__e)) {
__envp.SetPendingException (__e);
}
finally {
__envp.Dispose ();
}
}
}
}
Note that `jnimarshalmethod-gen.exe` will generate at
*packaging-time* what is currently done at *runtime* within
`JNINativeWrapper` using `System.Reflection.Emit`. This avoids the
need to use `System.Reflection.Emit` during process startup, so long
as the type contains `jnimarshalmethod-gen.exe`-generated types.
Note that `AndroidValueManager` needs to override `PeekPeer()`, as
the `__jvm.ValueManager.GetValue<T>()` invocation uses
`AndroidValueManager.PeekPeer()` as part of its operation:
android.runtime.JavaProxyThrowable: System.NotImplementedException: The method or operation is not implemented.
at Android.Runtime.AndroidValueManager.PeekPeer (Java.Interop.JniObjectReference reference) [0x00001]
at Java.Interop.JniRuntime+JniValueManager.PeekValue (Java.Interop.JniObjectReference reference) [0x0002f]
at Java.Interop.JniRuntime+JniValueManager.GetValue[T] (Java.Interop.JniObjectReference& reference, Java.Interop.JniObjectReferenceOptions options, System.Type targetType)
at Java.Interop.JniRuntime+JniValueManager.GetValue[T] (System.IntPtr handle) [0x0000a]
at xatemplateaot.MainActivity+__<$>_jni_marshal_methods.n_onCreate_Landroid_os_Bundle_ (System.IntPtr __jnienv, System.IntPtr __this, System.IntPtr savedInstanceState) [0x0001e]
at md58018c7d08c228c8e2a3e03723c59ca27.MainActivity.n_onCreate(Native Method)
at md58018c7d08c228c8e2a3e03723c59ca27.MainActivity.onCreate(MainActivity.java:29)
0 commit comments