Android Question Pass more than 3 arguments from B4A to WebView Javascript function

max123

Well-Known Member
Licensed User
Longtime User
I all,

for my 3D printing host app I had necessity to add a 3D view and found a good start point, I started from here:
https://www.b4x.com/android/forum/threads/b4x-using-three-js-webgl-in-a-webview.127277/

Many Thanks to user @roumei for posting it, this library is quite impressive and works very well even on my old phone a full HW accelleration is archived, just need a browser that support WebGL. Now I'm able to create a full 60 fps GL accelerated 3D view and construct my 3D scene in a way I've in mind.

Starting from @roumei example I studied it and extended a bit the class to create more geometries and add more functionalities.

To Learn fast THREEJS I've decided to make a simple app to interact with it in realtime. This app use a TabHost and have 3 tabs I've created two releases of this app, one with Javascript injected using WebViewExtras.executeJavascript in realtime, and other that collect a full HTML string then send it to a WebView.

- in the first Tab I put a ScrollView with a long EditText, here I write directly the Javascript code to be executed in a webview, this code is then added to an HTML template that import three.js and orbitcontrols.js. In the EditText I do not see the HTML file, just the Javascript to put inside the HTML <script> tag.
- in the second tab I put a WebView in fullscreen, when I press the Tab the app pack all HTML string with Javascript too and load it in the WebView, this work very well and just by changing the JS code in the EditText the final result change.
- in the last Tab (not implemented yet) I want to show a full HTML string with scripts, then add a button to Save and another to Load. This way, by just click on the created Index.html file it launches on the browser.

All these worked well, just I do not have the console, if I only miss a semicolon or there are some JS errors, executing it just do not show nothing in a WebView.... Next If I've success I try to integrate a console like Eruda.

Now my problem is that I want integrate this inside my app and call from B4A the Javascript functions to draw lines, cylinders that simulate a real plastic filament, and much more.... so definitely, I need to replace my old View.
The big problem I found is that some functions expets 5-8-10 arguments and working with WebViewExtras I've read that can be used max 3 arguments.

Is there a way to solve this limitation or maybe use some JavaObject or Reflection code to pass more arguments to a JS function ?
Maybe is possible to send an Object like a Type or maybe an array of parameters or other ways ?

Note that because in my app I use the UltimateWebView library I will use it at the end not both libraries, but I think this is not a problem because Javascript interface uses the same syntax.

Many thanks for your suggestions
 
Last edited:

max123

Well-Known Member
Licensed User
Longtime User
You can send a character delimited argument and regex.split it inside your script to get all arguments you need.
Not bad idea this....
but regex.split I think is not involved, I send from B4A then I need to split on JS side....
Note that it need to be executed as fast possible, it is called from 200 to 300 times every second, so very time critical.
Many thanks for suggestion
 
Last edited:
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
Not bad idea this....
but regex.split I think is not involved, I send from B4A then I need to split on JS side....
Note that it need to be executed as fast possible, it is called from 200 to 300 times every second, so very time critical.
Many thanks for suggestion
I meant the "split" function inside js.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Like this one @mc73 ?
JSON:
const str = 'one,two.three four';

const result = str.split(/[,.\s]/);

// 👇️ ['one', 'two', 'three', 'four']
console.log(result);

IMHO Regex is fast I already use it to process lines (read from gcode file, coordinates) to draw on.
 
Last edited:
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
Like this one @mc73 ?
JSON:
const str = 'one,two.three four';

const result = str.split(/[,.\s]/);

// 👇️ ['one', 'two', 'three', 'four']
console.log(result);

IMHO Regex is fast I already use it to process lines (read fron gcode file, coordinates) to draw on.
Yes. I don't think you're going to have a problem with speed, but testing should be done of course.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
So you think this is an approchable solution?
No others?
Maybe an array can be faster than split a delimiter string, but need to lead with different data types, Float, Int, Byte, String.

And what if I send just an Object like a Type or so on, can be recognized on JS side? Different approach from B4X and JS right ?
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
But I cannot manipulate the WebVew with JavaObject in a way I can send an Array of parameters?
Somewhat like this securely wrong.....

B4X:
    '''' TEST ''''
    Dim jo As JavaObject = mWebView
    Log(jo.RunMethod("stringByEvaluatingJavaScriptFromString:", Array("myFunction(arg1, arg2, arg3, arg4, arg5, arg6)")))
    
    Dim html As String = jo.RunMethod("stringByEvaluatingJavaScriptFromString:",Array("document.documentElement.innerText"))
    Log(html)
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Here my test...

I cannot manipulate WebView with JavaObject or inline Java or pass an array ?

Attached a screenshot as @mc73 suggestion.
I even used trim() to avoid problems, but maybe not needed.
The problem on this is that in B4A side I need to do the inverse operation, so get all arguments and use StringBuilder to construct a comma separated string to send with WebViewExras.executeJavaScript function as the only parameter.

Is this the best way?
Suggestions are welcome!
 

Attachments

  • Screen Shot 03-31-22 at 09.06 PM.PNG
    Screen Shot 03-31-22 at 09.06 PM.PNG
    68.7 KB · Views: 138
Last edited:
Upvote 0

aeric

Expert
Licensed User
Longtime User
send an Object like a Type
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Thanks for reply, because I have more than one function and each have different arguments the use of Type result impraticable.
The only solution can be to create a Type for any function I call.
Even on JS side I'm not sure it can recognize the Type as an Object and extract values from it.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Why not use JSON to pass all values as name-value pairs?
It is easy in Javascript to work with json.
Many thanks @DonManfred for your suggestion ,

this can be another option but need to test performances.

Using a string with delimiter seem to be the most compatible for now, even in other use cases, it can work with all platforms, eg. even to exchange data over network with Arduino, ESP8266 and ESP32 or other devices without use any addictional libraries.

Some time ago I wrote a library for ESP8266 and ESP32 where I send B4X commands like a function and passing arguments like a function, so call a function over nerwork by passing a function name with all arguments, then extracted on the receiver side. It use a comma separeted string and works well and fast... So the work I do with it is to call B4X functions like this:
B4X:
VirtualDisplay.DrawLine(x0, y0, x1, y1, Color, StrokeWidth)
On this B4A/B4J receive the command over WiFi, extract it and execute a clear B4X command, in this case this:
B4X:
Canvas.DrawLine(x0, y0, x1, y1, Color, StrokeWidth)
Using this method I've wrapped all Canvas functions and I can draw with ESP on my phone/tablet as I use it directly from B4A/B4J.

As I wrote, this worked really well and fast (like I can send/receive 500 and more commands every second over UDP or TCP) and no libraries required on both sides, just a string manipulation to pack/unpack a comma separated string.
There is no reason to specify the argument name, I do not used it, just it can retrieved from it's position in the comma delimited string like any normal function called locally.

Need to test Json strings as your suggestion, but eg. on arduino side it require the JSON library, using delimiter here seem to be more praticable.

And maybe use a normal Map can be praticable? But best a List ? Note that here is important the arguments order that must not changed.
Probably no because these are B4X only collection implementation and require to write a function to extract it, what you think on this?

Many thanks
 
Last edited:
Upvote 0
Top