Xamarin Android two way communication between Java

2020-04-06 06:40发布

问题:

I am developing an app using Xamarin Android which has a WebView displaying a web page. I want to implement a two way communication between Javascript from WebView to c#. I could call C# from Javascript using this link. However i couldn't find a way to send data back from C# to Javascript. Is there a way to send data back and forth in this approach. I thought writing a callback in Javascript would work but how to fire it from C# code.

Now, My problem is how to call WebView from a javascript interface class. I have a Javascript interface class as mentioned https://developer.xamarin.com/recipes/android/controls/webview/call_csharp_from_javascript/ namespace ScannerAndroid { public class JSInterface: Java.Lang.Object { Context context; WebView webView;

    public JSInterface (Context context, WebView webView1)
    {
      this.context = context;
      this.webView = webView1;
    }

    [Export]
    [JavascriptInterface]
    public void ShowToast()
    {
      Toast.MakeText (context, "Hello from C#", ToastLength.Short).Show ();
      this.webView.LoadUrl ("javascript:callback('Hello from Android Native');");

    }   
  }
}

The code throws an exception at LoadUrl line. java.lang.Throwable: A WebView method was called on thread 'Thread-891'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {42ce58a0} called on null, FYI main Looper is Looper (main, tid 1) {42ce58a0})

Now i am struggling how to refer the WebView from this Java script interface class

回答1:

Yes. That is possible. If you are targeting KitKat or higher you can use:

webView.EvaluateJavascript("enable();", null);

Where in this case enable(); is a JS function.

If you are targeting lower API levels you can use LoadUrl();:

webView.LoadUrl("javascript:enable();");

EDIT:

The error you get where it complains on LoadUrl is because it for some reason happens on a non-UI thread.

Since you have already passed on the Context into your JavascriptInterface class, then you can simply wrap the contents of ShowToast in:

context.RunOnUiThread(() => {
   // stuff here
});

Just change signature from Context to Activity and it should help you marshal you back on UI thread.