[mono-android] ItemizedOverlay does does not work
Jonathan Pryor
jonp at xamarin.com
Tue Nov 1 15:47:23 EDT 2011
On Nov 1, 2011, at 8:41 AM, Tomasz Cielecki wrote:
> By the way, is there a temporary solution in form of using JNI or
> something to implement the method?
See the attached patch.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: maps.patch
Type: application/octet-stream
Size: 3039 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/monodroid/attachments/20111101/ed9c2ab4/attachment.obj
-------------- next part --------------
You're not expected to understand that. :-)
It's also a new area, that we really need to document, but there are three things of note in that patch:
1. Android.Runtime.RegisterAttribute.DoNotGenerateAcw is a property (introduced in 1.9.x) which prevents generation of Android Callable Wrappers. This prevents the packaging process from trying to generate a "com.google.android.maps.ItemizedOverlay" type.
This allows us to create a new type which "mirrors" a Java type:
[Register ("com/google/android/maps/ItemizedOverlay", DoNotGenerateAcw=true)]
abstract class FixedItemizedOverlay : ItemizedOverlay {
Here, FixedItemizedOverlay has the same Java type as ItemizedOverlay -- com.google.android.maps.ItemizedOverlay.
2. Every member that needs to be exposed to Java code needs to have a [Register] attribute. Note that the constructor and the CreateItem() members both have [Register] attributes.
The [Register] attribute has three parameters of note: The JNI name ("<init>" for constructors, "createItem" for the method), the JNI signature, and a "connector method."
3. There's a lot of boilerplate for the connector method. :-)
The connector method is a static method which returns a System.Delegate and takes no parameters, and is called to get a delegate which is a JNI method suitable for use with JNIEnv::RegisterNatives:
http://download.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html#wp17734
If you look closely, every parameter of [Register] corresponds to a field of the JNINativeMethod JNI struct, and the delegate returned from the "connector method" needs to have the appropriate JNI method signature. Since in JNI, the first parameter is always a JNIEnv pointer, the second parameter is either the instance reference or a class reference, followed by any method parameters, the JNI signature we need is:
static IntPtr _CreateItem(IntPtr /* JNIEnv* */ env, IntPtr /* jobject */ __self, int index) {...}
The connector method thus returns a delegate which references the JNI method to register.
Which brings us to the JNI method itself, which needs to map JNI parameters into actual managed types, for which we use Java.Lang.Object.GetObject<T>():
FixedItemizedOverlay self = Java.Lang.Object.GetObject<FixedItemizedOverlay>(__self, JniHandleOwnership.DoNotTransfer);
Finally, our JNI method needs to return a Java value. You could do:
return value == null ? IntPtr.Zero : value.Handle;
though JNIEnv.ToJniHandle(value) is easier to do.
Hope this helps,
- Jon
More information about the Monodroid
mailing list