iOS Question WKWebview custom js

Emme Developer

Well-Known Member
Licensed User
Longtime User
Hi to all
I'm trying to use WKWebview with a local html, load from assets. I've a list of questions:
- Is possible to load a js local, inside assets?
- Is possible to call js functions in webview from B4i?
- Is possible to call sub of B4i from webview?

I'm trying to port an application i made in Nativescript into this language, so i suppose that there is a way to achieve all i've done in ns.
Thanks all
 

Emme Developer

Well-Known Member
Licensed User
Longtime User
LoadUrl will not work with assets files. You will need to copy all files to a different folder once when your app starts.

You can run JavaScript with EvaluateJavaScript.

You can trigger the OverrideUrl event from the JavaScript code.
Thanks for the answer! Is there another way instead using OverrideUrl? Html inside Webview is a single page application with dynamic content, so i don't go into another url.
Thanks
 
Upvote 0

Emme Developer

Well-Known Member
Licensed User
Longtime User
I saw in many links, for example this, that is possibile to implement such thing by passing the controller inside WKWebview, or by using webkit messagehandler, but i don't know how achieve this
 
Upvote 0

Jack Cole

Well-Known Member
Licensed User
Longtime User
You don't go into another URL. You just attempt to go to a URL from the js, and then override it in the sub. Here's some example code from one of my apps.

B4X:
Sub wv_OverrideUrl (Url As String) As Boolean
    Log("override url")
    Log(Url)
    Dim shouldoverride=False As Boolean

    If Url.IndexOf("http")>-1 Or Url.IndexOf("mailto:")>-1 Then
        Dim App As Application
        App.OpenURL(Url)
        shouldoverride=True
    End If

    If Url.IndexOf("ReminderEnabledCheck")>-1 Then
        ReminderEnabledCheck
        shouldoverride=True
    End If
   
    If Url.IndexOf("log:")>-1 Then
        LogColor(Url.Replace("log:","").Replace("%20"," "),Colors.Yellow)
        shouldoverride=True
    End If

    If Url.IndexOf("sleeplog")>-1 Then
        Dim l As List
        l.Initialize2(Regex.Split("%5E",Url))
        If l.size=3 Then
            ShowSleepLog(l.Get(1),l.Get(2))
        Else
            ShowSleepLog(l.Get(1),"")
        End If
    End If
    Return shouldoverride
End Sub

On the js side, it's pretty simple. I just send add the parameters to the URL separated by ^. I parse it out in the overrideUrl function in b4i.

B4X:
function sendPlatformMessage(platform, message, param) {
    if (Ext.Ajax.enableExternalNotify) {
        if (platform == "Android") {
            b4a.CallSub(message,true, param);
        }
        if (platform == "iOS") {
            window.location.href = message + "^" + param;
        }
    }
}
 
Last edited:
Upvote 0

Emme Developer

Well-Known Member
Licensed User
Longtime User
Found another solution, without using OvverideUrl. This is the code
B4X:
' Create WKWebView1

    WKWebView1 = CreateWKWebView(Page1.RootPanel)
    WKWebView1.LoadUrl("file://" & File.Combine(File.DirLibrary, yourpath))

Sub CreateWKWebView (pnl As Panel) As View
    Dim conf As NativeObject
    conf = conf.Initialize("WKWebViewConfiguration").RunMethod("new", Null)
   
    Dim NativeMe As NativeObject = Me
    conf = NativeMe.RunMethod("getconfig:", Array(conf))
   
    Dim wk As NativeObject
    Dim p As NativeObject = pnl
    wk = wk.Initialize("WKWebView").RunMethod("alloc", Null)
    wk.RunMethod("initWithFrame:configuration:", Array(p.RunMethod("frame", Null), conf))
    pnl.AddView(wk, 0, 0, pnl.Width, pnl.Height)
    Return wk
End Sub

Private Sub JSCallback(body As Object)
    Log(body)
End Sub

#If OBJC
#import <Foundation/Foundation.h>

- (WKWebViewConfiguration *) getconfig: ( WKWebViewConfiguration *)config
{
       WKUserContentController* userController = [[WKUserContentController alloc]init];
       [userController addScriptMessageHandler:self name:@"callback"];
    config.userContentController = userController;
 
  return config;
}


- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message     {
if ([message.name isEqualToString:@"callback"]) {
        [self.bi raiseEvent:nil event:@"jscallback:"params:@[message.body]];
}
}
#End If

JS Functions
B4X:
 window.webkit.messageHandlers.callback.postMessage({
        "name": "Lily",
        "breed": "Pug",
        "age": 1
    });
 
Upvote 0
Top