[mono-android] JNI Help Please

Jonathan Pryor jonp at xamarin.com
Tue Jan 17 01:45:45 UTC 2012


On Jan 16, 2012, at 8:06 PM, digitalml wrote:
> I still have the issue of the callback though. What happens in the .java code is that when a hardware event occurs it fires the onReceiveMsgCardData() event.

My question from before remains the same: what code is calling onReceiveMsgCardData() and how does that code obtain the instance on which to call onReceiveMsgCardData()? That wasn't clear to me.

So let me assume something: the `uniMagReader` instance is responsible for calling onReceiveMsgCardData(), and the `uniMagReader` initialization is done within jni_helper.InitializeReader(). If that's the case, you could declare a Managed Callable Wrapper for `jni_helper` within C# (note: completely untested and uncompiled):

	[Register ("MagHelper/jni_helper", DoNotGenerateAcw=true)]
	class YourJniHelper : Java.Lang.Object {

		public YourJniHelper ()
		{
		}

		public YourJniHelper (IntPtr handle, JniHandleOwnership transfer)
			: base (handle, transfer)
		{
		}

		static IntPtr class_ref = JNIEnv.FindClass ("MagHelper/jni_helper");

		protected override Type ThresholdType {
			get {return typeof (YourJniHelper);}
		}

		protected override IntPtr ThresholdClass {
			get {return class_ref;}
		}

		static IntPtr id_InitializeReader;
		public void InitializeReader ()
		{
			if (id_InitializeReader == IntPtr.Zero)
				id_InitializeReader = JNIEnv.GetMethodID(class_ref, "InitializeReader", "()V");
			JNIEnv.CallVoidMethod (Handle, id_InitializeReader);
		}

		static IntPtr id_onReceiveMsgCardData;

		[Register ("onReceiveMsgCardData", "(B[B)V", "Get_onReceiveMsgCardData_Handler")]
		public virtual void OnReceiveMsgCardData (sbyte flagOfCardData, JavaArray<byte> cardData)
		{
			if (id_onReceiveMsgCardData == IntPtr.Zero)
				id_onReceiveMsgCardData = JNIEnv.GetMethodID(class_ref, "onReceiveMsgCardData", "(B[B)V");
			if (GetType () == ThresholdType) {
				JNIEnv.CallVoidMethod (Handle, id_onReceiveMsgCardData,
						new JValue (flagOfCardData),
						new JValue (JNIEnv.ToJniHandle (cardData)));
				return;
			}
			JNIenv.CallNonvirtualVoidMethod (Handle, ThresholdClass, id_onReceiveMsgCardData,
					new JValue (flagOfCardData),
					new JValue (JNIEnv.ToJniHandle (cardData)));
		}

		static Delegate cb_onReceiveMsgCardData;
		static Delegate Get_onReceiveMsgCardData_Handler ()
		{
			if (cb_onReceiveMsgCardData == null)
				cb_onReceiveMsgCardData = JNINativeWrapper.CreateDelegate ((Action<IntPtr, IntPtr, sbyte, IntPtr>) n_OnReceiveMsgCardData);
			return cb_onReceiveMsgCardData;
		}

		static void n_OnReceiveMsgCardData (IntPtr jnienv, IntPtr lrefThis, byte flagOfCardData, IntPtr n_cardData)
		{
			YourJniHelper __this = Java.Lang.Object.GetObject<YourJniHelper>(lrefThis, JniHandleOwnership.DoNotTransfer);
			using (var cardData = new JavaArray<byte>(n_cardData, JniHandleOwnership.DoNotTransfer))
				__this. OnReceiveMsgCardData (flagOfCardData, cardData);
		}
	}

then subclass it:

	class MyJniHelper : YourJniHelper {
		public override void OnReceiveMsgCardData (sbyte flagOfCardData, IntPtr cardData)
		{
			/* ... */
		}
	}

then use it:

	var helper = new MyJniHelper ();
	helper.InitializeReader ();

You're not currently expected to understand the Managed Callable Wrapper; docs for that are in-progress, though you can follow the existing sample:

	The base Java class: https://github.com/xamarin/monodroid-samples/blob/master/SanityTests/Adder.java
	The C# glue code for inheritance: https://github.com/xamarin/monodroid-samples/blob/master/SanityTests/ManagedAdder.cs
	The C# subclass of the Java type: https://github.com/xamarin/monodroid-samples/blob/master/SanityTests/ManagedAdder.cs#L155

 - Jon
 


More information about the Monodroid mailing list