Ronak Shetiya
Ronak Shetiya

Reputation: 980

How to Load Javascript from WebApi In Hybrid Webview Xamarin forms

I am trying to create a hybrid webview which is going to get its html data from the web api, the data which api is returning is in the form of string. The problem which i am facing right now i am not able to bind or load the url of web on my hybrid webview i am not able to understand where the thing has to be change.

Here is the code which i have tried till now but could not make it work

here is custom control

public class HybridWebView : View
{
    Action<string> action;

    public static readonly BindableProperty UriProperty = BindableProperty.Create(
        propertyName: "Uri",
        returnType: typeof(string),
        declaringType: typeof(HybridWebView),
        defaultValue: default(string));

    public string Uri
    {
        get { return (string)GetValue(UriProperty); }
        set { SetValue(UriProperty, value); }
    }

    public void RegisterAction(Action<string> callback)
    {
        action = callback;
    }

    public void Cleanup()
    {
        action = null;
    }

    public void InvokeAction(string data)
    {
        if (action == null || data == null)
        {
            return;
        }
        action.Invoke(data);
    }
}

Here is my custom renderer for Android

 public class HybridWebViewRenderer : ViewRenderer<HybridWebView, Android.Webkit.WebView>
{
    const string JavascriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";
    Context _context;

    public HybridWebViewRenderer(Context context) : base(context)
    {
        _context = context;
    }


    protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
    {
        base.OnElementChanged(e);

        if (Control == null)
        {
            var webView = new Android.Webkit.WebView(_context);
            webView.Settings.JavaScriptEnabled = true;
            webView.SetWebViewClient(new JavascriptWebViewClient($"javascript: {JavascriptFunction}"));
            webView.Settings.BuiltInZoomControls = true;
            webView.Settings.DisplayZoomControls = false;

            webView.Settings.LoadWithOverviewMode = true;
            webView.Settings.UseWideViewPort = true;
            Control.LoadUrl($"{Element.Uri}");
            SetNativeControl(webView);
        }
        if (e.OldElement != null)
        {
            Control.RemoveJavascriptInterface("jsBridge");
            var hybridWebView = e.OldElement as HybridWebView;
            hybridWebView.Cleanup();
        }
        if (e.NewElement != null)
        {
            Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
            ///Control.LoadUrl($"{Element.Uri}");
        }
    }}

Here is my IOS Renderer

public class HybridWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>, IWKScriptMessageHandler
{
    const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";
    WKUserContentController userController;

    protected override void OnElementChanged (ElementChangedEventArgs<HybridWebView> e)
    {
        base.OnElementChanged (e);

        if (Control == null) {
            userController = new WKUserContentController ();
            var script = new WKUserScript (new NSString (JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
            userController.AddUserScript (script);
            userController.AddScriptMessageHandler (this, "invokeAction");

            var config = new WKWebViewConfiguration { UserContentController = userController };
            var webView = new WKWebView (Frame, config);
            SetNativeControl (webView);
        }
        if (e.OldElement != null) {
            userController.RemoveAllUserScripts ();
            userController.RemoveScriptMessageHandler ("invokeAction");
            var hybridWebView = e.OldElement as HybridWebView;
            hybridWebView.Cleanup ();
        }
        if (e.NewElement != null) {
            string fileName = Path.Combine (NSBundle.MainBundle.BundlePath, string.Format ("Content/{0}", Element.Uri));
            Control.LoadRequest (new NSUrlRequest (new NSUrl (fileName, false)));
        }
    }

    public void DidReceiveScriptMessage (WKUserContentController userContentController, WKScriptMessage message)
    {
        Element.InvokeAction (message.Body.ToString ());
    }
}

here is the code reference from i took this this

this is where i am giving a source to webview from my webapi in my common library

  var ee = await PolicyService.GetPrivacyPolicy();
        var et = await PolicyService.GetTermsPolicy();

        var htmlprivarcy = new HtmlWebViewSource
        {
            Html = ee
        };

        var htmlforterms = new HtmlWebViewSource
        {
            Html = et
        };
        Privacy.Uri = ee;

Upvotes: 0

Views: 1002

Answers (1)

Leo Zhu
Leo Zhu

Reputation: 14956

hybrid webview which is going to get its html data from the web api

You get HTML data, not a url, so

Android:

you shouldn't use Control.LoadUrl($"{Element.Uri}"); method when you load it,change it to Control.LoadData($"{Element.Uri}","text/html","utf-8");

ios:

change Control.LoadRequest to Control.LoadHtmlString($"{Element.Uri}", null);

Upvotes: 1

Related Questions