[mono-android] WebView Javascript Interface and exposing methods through JNI

Tomasz Cielecki tomasz at ostebaronen.dk
Mon Jan 9 04:57:51 EST 2012


Ok, I have been messing around a bit with this JNI stuff and can't
seem to get it to work. The C# code compiles fine, so it must be the
Java code that fails somehow as I get two errors:

"C:\Users\tcielecki\Desktop\MonoDroid.WAToolkit\MonoDroid.WAToolkit\MonoDroid.WAToolkit.Sample.csproj"
(SignAndroidPackage target) (1) ->
(_CompileJava target) ->
  obj\Debug\android\src\monodroid\watoolkit\library\login\AccessControlWebAuthActivity_AccessControlJavascriptNotify.java(5,43):
javac error :  cannot find symbol
[C:\Users\tcielecki\Desktop\MonoDroid.WAToolkit\MonoDroid.WAToolkit\MonoDroid.WAToolkit.Sample.csproj]
obj\Debug\android\src\monodroid\watoolkit\library\login\AccessControlWebAuthActivity_AccessControlJavascriptNotify.java(5,43):
javac error : symbol  : class AccessControlJavascriptNotify
[C:\Users\tcielecki\Desktop\MonoDroid.WAToolkit\MonoDroid.WAToolkit\MonoDroid.WAToolkit.Sample.csproj]
obj\Debug\android\src\monodroid\watoolkit\library\login\AccessControlWebAuthActivity_AccessControlJavascriptNotify.java(5,43):
javac error : location: package monodroid.watoolkit.library.login
[C:\Users\tcielecki\Desktop\MonoDroid.WAToolkit\MonoDroid.WAToolkit\MonoDroid.WAToolkit.Sample.csproj]
obj\Debug\android\src\monodroid\watoolkit\library\login\AccessControlWebAuthActivity_AccessControlJavascriptNotify.java(5,43):
javac error : 	extends
monodroid.watoolkit.library.login.AccessControlJavascriptNotify
[C:\Users\tcielecki\Desktop\MonoDroid.WAToolkit\MonoDroid.WAToolkit\MonoDroid.WAToolkit.Sample.csproj]
obj\Debug\android\src\monodroid\watoolkit\library\login\AccessControlWebAuthActivity_AccessControlJavascriptNotify.java(5,43):
javac error :  [C:\Users\tcielecki\Desktop\MonoDroid.WAToolkit\MonoDroid.WAToolkit\MonoDroid.WAToolkit.Sample.csproj]
  obj\Debug\android\src\monodroid\watoolkit\library\login\AccessControlWebAuthActivity_AccessControlJavascriptNotify.java(15,2):
error :  method does not override or implement a method from a
supertype [C:\Users\tcielecki\Desktop\MonoDroid.WAToolkit\MonoDroid.WAToolkit\MonoDroid.WAToolkit.Sample.csproj]
obj\Debug\android\src\monodroid\watoolkit\library\login\AccessControlWebAuthActivity_AccessControlJavascriptNotify.java(15,2):
error : 	@Override
[C:\Users\tcielecki\Desktop\MonoDroid.WAToolkit\MonoDroid.WAToolkit\MonoDroid.WAToolkit.Sample.csproj]
obj\Debug\android\src\monodroid\watoolkit\library\login\AccessControlWebAuthActivity_AccessControlJavascriptNotify.java(15,2):
error :  [C:\Users\tcielecki\Desktop\MonoDroid.WAToolkit\MonoDroid.WAToolkit\MonoDroid.WAToolkit.Sample.csproj]

Seems to me that it cannot find the java file I created even though I
have set the build action to AndroidJavaSource, can it have anything
to do with that I am doing this in a Mono for Android Class Library?

I have tried to follow the Adder/ManagedAdder samples very closely and
came up with this code, and as I said it compiles just fine.

AccessControlJavascriptNotify.java:

	package monodroid.watoolkit.library.login;

	public class AccessControlJavascriptNotify
	{
		public void notify(String securityTokenResponse) { }
	}
	
ManagedAccessControlJavascriptNotify.cs:

	using System;
	using Android.Runtime;
	
	namespace MonoDroid.WAToolkit.Library.Login
	{
		[Register("monodroid/watoolkit/library/login/AccessControlJavascriptNotify",
DoNotGenerateAcw = true)]
		public abstract class ManagedAccessControlJavascriptNotify : Java.Lang.Object
		{
			static IntPtr class_ref =
JNIEnv.FindClass("monodroid/watoolkit/library/login/AccessControlJavascriptNotify");
	
			public ManagedAccessControlJavascriptNotify ()
			{
			}

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

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

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

			#region Notify
			static IntPtr id_notify;

			[Register("notify", "(Ljava/lang/String;)V", "GetNotifyHandler")]
			public virtual void Notify(string securityTokenResponse)
			{
				if (id_notify == IntPtr.Zero)
					id_notify = JNIEnv.GetMethodID(class_ref, "notify",
"(Ljava/lang/String;)V");
				if (GetType() == ThresholdType)
					JNIEnv.CallVoidMethod(Handle, id_notify, new JValue[] { new
JValue(new Java.Lang.String(securityTokenResponse)) });
				else
					JNIEnv.CallNonvirtualObjectMethod(Handle, ThresholdClass,
id_notify, new JValue[] { new JValue(new
Java.Lang.String(securityTokenResponse)) });
			}

#pragma warning disable 0169
			static Delegate cb_notify;
			static Delegate GetNotifyHandler()
			{
				if (cb_notify == null)
					cb_notify = JNINativeWrapper.CreateDelegate((Action<IntPtr,
IntPtr, string>)n_Notify);
				return cb_notify;
			}

			static void n_Notify(IntPtr jnienv, IntPtr lrefThis, string a)
			{
				ManagedAccessControlJavascriptNotify __this =
Java.Lang.Object.GetObject<ManagedAccessControlJavascriptNotify>(lrefThis,
JniHandleOwnership.DoNotTransfer);
				__this.Notify(a);
			}
			#endregion
#pragma warning restore 0169
		}
	}

And in my activity where I need this I have done:

        public class AccessControlJavascriptNotify :
ManagedAccessControlJavascriptNotify
        {
            public override void Notify(string securityTokenResponse)
            {
                base.Notify(securityTokenResponse);
            }
        }

Any Ideas?


On Thu, Jan 5, 2012 at 8:38 PM, Tomasz Cielecki <tomasz at ostebaronen.dk> wrote:
> Thank you Jon,
>
> I will see if I can get this to work.
>
> On Jan 5, 2012 6:53 PM, "Jonathan Pryor" <jonp at xamarin.com> wrote:
>>
>> On Jan 5, 2012, at 4:50 AM, Tomasz Cielecki wrote:
>> > I am trying to add a javascript interface to my webview but it the
>> > method in the object I pass to the webview does not get triggered.
>> ...
>> > I was thinking whether it is possible to tell mandroid to put the
>> > methods in the generated Java files, so that Java knows of them.
>>
>> Yes, though as you saw it breaks because the Android Callable Wrapper use
>> @Override, which breaks you.
>>
>> The solution [0] is a level of indirection: declare a Java-side interface,
>> then bind that interface in C# and implement it. You'll still need to write
>> some Java code, but only the interface declaration.
>>
>> Unfortunately, binding interfaces is more complicated. Fortunately, I have
>> a sample:
>>
>>
>>  https://github.com/xamarin/monodroid-samples/blob/master/SanityTests/Adder.java
>>
>>  https://github.com/xamarin/monodroid-samples/blob/master/SanityTests/ManagedAdder.cs
>>
>> I also have docs, but those are awaiting review.
>>
>>  - Jon
>>
>> [0] Yes, this isn't a very good solution. We'll be working on improving
>> this in future releases.
>>
>> _______________________________________________
>> Monodroid mailing list
>> Monodroid at lists.ximian.com
>>
>> UNSUBSCRIBE INFORMATION:
>> http://lists.ximian.com/mailman/listinfo/monodroid



-- 
Med Venlig Hilsen / With Best Regards
Tomasz Cielecki
http://ostebaronen.dk


More information about the Monodroid mailing list