1

We are implementing an app where we have communication between Javascript and c#. Our UIWebView has a button to invoke some native functionality. On a UIWebView i have an handler on ShouldStartLoad.

webView.ShouldStartLoad = myHandler; 
bool myHandler (UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navType)
{
}

This gets called everytime page loads. Indeed, i would like to only call it from an event from WebView such as on a button click. From Javascript i have

window.location.href = "myapp://action?par1=abc&par2=def";

How to call a particular function from custom url?

Calling JavaScript from c#

I am trying to call back JavaScript from c# but it is not calling TestShow() function

 wkWebView.EvaluateJavaScript(string.Format("TestShow()"), (r, e) =>
    {
        Console.WriteLine("In EvaluateJavaScript");
        if (e != null) Console.WriteLine(e);
    });

JavaScript side i have a Alert but it is not showing that alert

function TestShow()
{
    alert("Hello! I am an alert box!!");
}
3
  • Have you thought about using the HybridKit plugin github.com/chkn/HybridKit? Commented Apr 11, 2016 at 23:36
  • Not really HybridKit. I tried JSBridge but it has some limitations and not working in our case. So i want to do it without any plugin Commented Apr 12, 2016 at 0:03
  • Do you know if HybridKit plugin good for the App store submission. Commented Apr 12, 2016 at 18:17

1 Answer 1

6

You can either continue using UIWebView and parse the NSUrlRequest to see if it is the call you're looking for. Then return true/false accordingly.

A better option would be to use WKWebView and create a custom message handler. Something like this:

1) Implement IWKScriptMessageHandler (tested on the default UIView created by Xamarin UIViewController)

public class UniversalView : UIView, IWKScriptMessageHandler
{
    public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
    {
        var msg = message.Body.ToString();
        System.Diagnostics.Debug.WriteLine(msg);
    }
}

2) Create user controller with a handler for "myapp" (this = the IWKScriptMessageHandler)

        var userController = new WKUserContentController();
        userController.AddScriptMessageHandler(this, "myapp");

3) Create a config with the controller

        var config = new WKWebViewConfiguration
        {
            UserContentController = userController
        };

4) Create the WKWebView with the config

var webView = new WKWebView(new CGRect(10, 100, 500, 500), config);

5) Call "myapp" from your JS code

        <html><head><meta charset = "utf-8"/></head><body>
            <button onclick="callCsharp()">Click</button>"
            <script type="text/javascript">
                function callCsharp(){ 

window.webkit.messageHandlers.myapp.postMessage("action?par1=abc&par2=def");

                 }</script></body></html>";

EDIT: In regards to evaluating JS from C# you need to be sure the HTML page has finished loading or otherwise the call will result in an error. You can handle navigation events by implementing IWKNavigationDelegate

public class UniversalView : UIView, IWKScriptMessageHandler, IWKNavigationDelegate
{

    [Export("webView:didFinishNavigation:")]
    public void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
    {
        webView.EvaluateJavaScript("callCsharp()", (result, error) =>
        {
            if (error != null) Console.WriteLine(error);
        });
    }

Assign it to the WKWebView you created:

        var webView = new WKWebView(new CGRect(10, 100, 500, 500), config)
        {
            WeakNavigationDelegate = this
        };
Sign up to request clarification or add additional context in comments.

5 Comments

Calling back the Javascript from c# using WKWebView EvaluateJavaScript not working. It does not call wkWebView.EvaluateJavaScript(string.Format("TestShow()"),null);
To ensure you're calling it from the UI thread you might want to try wrapping it around InvokeOnMainThread(() => {}) call. Also add in the handler to see if there are errors in the JS side: (r, e) => { if (e != null) Debug.WriteLine(e); }
No luck in calling Javascript. I have edited my code above.
Are you sure it is called AFTER the page has loaded? See my edit.
Just a note in case anyone is having trouble wiring up their WKWebView to receive messages from Javascript, following SKall's post above. If you want to use an existing WKWebView instead of creating a new one as SKall shows, you can't provide a new Configuration because that property is read-only. You can set the UserContentController property of the existing Configuration object, but it doesn't do anything. However, you CAN call webView.Configuration.UserContentController.AddScriptMessageHandler(), and things will work properly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.