In Xamarin.Forms Gawa native app, make request-response from C # to JavaScript Task <T>

It's a memo, so it's miscellaneous.

scenario

--Xamarin.Forms + WebView (HTML, JavaScript SPA) Gawa native app --I want to enable / disable the BACK key of an Android application depending on the page state in WebView. --Since the data is being edited (unsaved), it will be a problem if history.back or the application is closed with the Back key.

flow

    1. [Forms side] ʻAction <TaskCompletionSource <bool >> OnRequestIsEnableBackKey {get; set;}
  1. [Forms side] Also grow Task <bool> IsEnableBackKeyAsync () in WebViewEx (extended WebView). The implementation is as follows.

public Task<bool> IsEnableBackKeyAsync()
{
    var comp = new TaskCompletionSource<bool>();

    if (OnRequestIsEnableBackKey != null)
    {
        OnRequestIsEnableBackKey.Invoke(comp);
    }
    else
    {
        comp.SetResult(false);
    }

    return comp.Task;
}
    1. [Android side] Create MyWebViewRenderer which is an extension of WebViewRenderer.

Four. Create a JavaScriptHandler by referring to Linking JavaScript with WebView of Xamarin.Forms (with iOS / Android common) --Qiita. In addition to Control in the constructor, pass `ʻe.NewElement as WebViewEx. The name of the argument is WebViewEx outer. The second argument of AddJavascriptInterface should be GawaApp``.

Five. Write the code to receive OnRequestIsEnableBackKey in the constructor of JavaScriptHandler.

private TaskCompletionSource<bool> isEnableBackKeyComp = null;

public JavaScriptHandler(Android.Webkit.WebView webView, WebViewEx outer)
{
    outer.OnRequestIsEnableBackKey = comp => 
    {
        isEnableBackKeyComp = comp;

        //Error if not called from main thread
        webView.Post(() =>
        {
            webView.EvaluateJavascript("window.requestIsEnableBackKey()", null);
            // webView.LoadUrl("javascript:window.requestIsEnableBackKey();");← This is still OK
        });
    };
}

In the process so far, when ʻawait webViewEx.IsEnableBackKeyAsync () is called on the Forms side, the JavaScript window.requestIsEnableBackKey () `function is called.

  1. Generate onResultCanExitApp in JavaScriptHandler. It is a method that the result is notified from the JavaScript side. as follows.
[Export]
[Android.Webkit.JavascriptInterface]
public void onResultIsEnableBackKey(bool value)
{
    isEnableBackKeyComp?.SetResult(value);
    isEnableBackKeyComp = null; // one shot
}

Calling GawaApp.onResultIsEnableBackKey (true or false) on the JavaScript side will call back this method. If you set a value to isEnableBackKeyComp, which is a TaskCompletionSource, the result of ʻawait webViewEx.IsEnableBackKeyAsync () on the Forms side will be returned.

    1. The JavaScript side is surely like this
window.requestIsEnableBackKey = () => {
  
  //Processing something

  GawaApp.onResultIsEnableBackKey(true or false);
}

I implemented it halfway, but I quit it because it was troublesome (I thought that unidirectional JavaScript → C # would be simpler), so I will leave only the idea.

Recommended Posts

In Xamarin.Forms Gawa native app, make request-response from C # to JavaScript Task <T>
I tried to move Hello World (+ α) written in C language from JavaScript [WebAssembly]
I tried to make an application in 3 months from inexperienced