executeInXojo undefined/not accessible

So I’ve looked through various other threads about this and have seen nothing about Android specifically and the MobileHTMLViewer embedded in it, I’ve seen people mention it only working under Webkit but I don’t think that’s something that can be changed here/on mobile in general.

Anyway, without giving too much backstory into research and getting to the actual issue/bug it. It seems that on Android specifically executeInXojo, and executeInXojoSync are never defined within the context of the MobileHTMLViewer.

This is the case regardless of whether or not it’s being called from within ExecuteJavaScript or from within the HTML that has been loaded on the page.

Here are some tests I attempted:
<script>executeInXojo("firetest","testparam");</script>
<script>function myFunction() { executeInXojo("firetest","testparam"); }</script>

Within the Xojo Code, calling “myFunction” via ExecuteJavaScript.

Within ExecuteJavaScript:
function execute_xojo() { executeInXojo("firetest","testparam"); }

Within the HTML:
<script>execute_xojo();</script>

None of the above worked and always claimed that execInXojo was undefined, I was testing this out to see if using Xojo for something I wanted to do was feasible on Android but it seems the Android support may still be in the early stages. Can anyone else confirm this isn’t functional or tell me if I’m being crazy?

I didn’t think this was implemented for Android yet, but I could be wrong. I haven’t done much with Android since the early releases and JavaScript communication is something I need.

Android’s MobileHTMLViewer is a little different from iOS.

This might help…

For Android, added MobileHTMLViewer.ExecuteJavaScript() method, JavaScriptResult event and JavaScriptRequest event. ExecuteJavaScript is asynchronous and its result appear in the JavaScriptResult event. To call the JavaScriptRequest event, use xojo.execute() in the JavaScript code. A method name and up to 5 parameters can be passed back to Xojo.

Source: https://tracker.xojo.com/xojoinc/xojo/-/issues/70949#note_560524

2 Likes

While this does seem to explain things, the documentation doesn’t specify that there’s a difference in Android, embarrassed to say I scoured the issues but only looked at open ones to see if any present open bugs were documenting this, not closed ones, and missed that as a result.

If I call xojo.execute("test") within the javascript of the HTML without doing it through ExecuteJavaScript() I seem to get “Java exception was raised during method invocation”. If I call xojo.execute("test"); within ExecuteJavaScript() nothing appears to happen but JavaScriptResult is fired, at the moment I tried to place it within a button and click that. I would expect that JavaScriptRequest would be triggered as a result of xojo.execute() based on documentation and that issue linked which is what I mean by ‘nothing seems to happen’ I have a messagebox defined within JavaScriptRequest which is never fired when xojo.execute is called.

For clarity this is what I have in my button as a test:
Dim JsCode as String JsCode = "xojo.execute('test'); WebViewer.ExecuteJavaScript(JsCode)

When I’m trying to execute it from the HTML directly, I also tried defining a function in Javascript via the DocumentComplete event, and then calling that function on click within my HTML page. The function does fire but xojo.execute() fails. Beyond that I’ve tried just directly calling xojo.execute() without defining the function utilizing ExecuteJavaScript (assuming that by defining it with ExecuteJavaScript that if it needed to be ‘created’ by Xojo it would have the proper reference to the object but maybe wishful thinking.

It seems you’ve been able to get this to work in the past though based on the history on the linked issue, so I’m curious what your test case was or if this is bugged in a later version and hasn’t been tested. At this point I’ve sort of moved on from using Xojo for what I’m trying to accomplish but still curious if I’m doing something wrong.

Also,
It’s unfortunate the documentation hasn’t been kept up to date on this, I know the Android support is still ‘beta’ but I recall when this stuff was reliable for RealBasic:
MobileHTMLViewer — Xojo documentation.

I’ve mostly only used Xojo for raspberry pi projects recently to prototype things quickly instead of relying on something like C#, but was hoping I could run it here as C# doesn’t run on android without Xamarin and stuff.

UPDATE: I was mistaken, and Martin T has kindly corrected me below. The documentation does briefly mention a difference for android, but it’s not clear and I think it should be improved.

Additionally, I discovered my issue WAS that I was executing a MessageBox within JavaScriptRequest it appears this runs on a JavaScriptBridge thread not the main application/UI thread meaning anything that interfaces with the UI here will fail, running logcat revealed this was what was going wrong when it was being called and why I was seeing the Java Invocation Exception thing.

So, it does appear to work if I do the following:

  1. Define a function via ExecuteJavaScript within the WebViewer on DocumentComplete event.
  2. Call the function via my javascript in the HTML page that I’ve defined in step 1.

I have not tried simply executing xojo.execute without first defining the function via ExecuteJavaScript yet but it does seem the implementation is there and does work as intended just not well documented in my opinion.

I also haven’t tested with parameters yet.

As far as I can see, the information is part of the docs, but only listed at the JavaScriptResult-Event section (MobileHTMLViewer — Xojo documentation)

1 Like

Ok, somehow I completely missed that or it’s not in the ‘local’ docs included with the application (when you press F1) unless it’s loading these live ones, and I apologize. It isn’t clear though under the JavaScriptRequest or elsewhere that executeInXojo is platform-specific. I was mostly looking in compatibility sections and the JavaScriptRequest area. I apologize for my misstatement but still believe that it should be cleaned up/more clearly stated how it’s utilized and that there are compatibility differences per platform.

This still appears to be largely non-functional to me.

Here are my test results:

'// Raises the event, but obviously no parameters.
htmlViewerInstance.ExecuteJavaScript("xojo.execute('testOne');")

'// Raises the event, but parameters array is empty.
htmlViewerInstance.ExecuteJavaScript("xojo.execute('testTwo', document.title);")

'// Raises the event, but parameters is an array with Nil as the sole value.
htmlViewerInstance.ExecuteJavaScript("xojo.execute('testTwo', 'someValue');")

'// Raises the event, but parameters is an array with Nil as the sole value.
htmlViewerInstance.ExecuteJavaScript("xojo.execute('testThree', [document.title]);")

'// Raises the event, but parameters is an array with Nil as the sole value.
htmlViewerInstance.ExecuteJavaScript("xojo.execute('testTwo', ['someValue']);")

'// Raises the event, but parameters has a nil value for only one of the two expected entries
htmlViewerInstance.ExecuteJavaScript("xojo.execute('testFour', [document.title, 'someValue']);")

'// Maybe it's a JSON object for parameters?
'   Nope. Result will be a string containing "null"
htmlViewerInstance.ExecuteJavaScript("xojo.execute('testFour', ['title':document.title, 'value':'someValue']);")

Additionally, if you have multiple calls to xojo.execute that occur too quickly together, they may fail to raise the JavaScriptRequest event or raise it with no associated data. I had to do a lot of comment toggling, then running again, which takes forever because the debug process is painfully slow (at least for me).

And the API is lacking. I’m assuming that this is just incomplete at this point.

I did update my post with an update that the event did seem to be fired, debugger maybe wasn’t catching it because of the fact I had a try-catch block in the javascript, not sure. I haven’t tried with parameters yet but I think you’re right and it hasn’t been made a priority as most people probably aren’t reliant on this behavior.

Added arguments now,
I was able to read them as well.

So the following works:
In JavaScriptRequest:

Timer1.Enabled = True
MyVar = parameters(0).StringValue
Timer1.Reset()

Defined a timer with something like MessageBox since the timer would execute on the UI thread, in DocumentComplete I did the following:

Dim JsCode As String
JsCode = "function MyFunction() { xojo.execute(""test"",""test""); }"
WebViewer.ExecuteJavaScript(jsCode)

Then in the HTML:
<script>MyFunction()</script>

This all seemed to work fine, JavaScriptRequest was fired successfully and etc. So I guess the main thing was just that xojo.execute was needed and I didn’t know that it wouldn’t be executing on the UI thread.

Hopefully this helps someone else looking for answers on how this works in the future, fwiw; I don’t think it’s required to use ExecuteJavaScript and I think the binding exists in the HTMLViewer for any HTML loadeded regardless. Meaning you can probably use xojo.execute without needing to define it in a function with ExecuteJavaScript but I haven’t tested it.

EDIT:
Confirmed, xojo.execute also works perfectly fine without it being triggered from ExecuteJavaScript just from the HTML loaded in the page and my problem all along with the combination of:

  1. Not realizing that the JavaScriptRequest event is not executed within the UI thread.
  2. Not realizing that xojo.execute is the proper way to talk to the bridge via JS instead of executeInXojo.