0

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;
2

1 Answer 1

1

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);

Sign up to request clarification or add additional context in comments.

Comments

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.