Search code examples
javafxmobilegluonjavafxports

FXML Script Event Handlers support on mobile


I want to use scripted event handlers in fxml file in a javafx app, which is supposed to run on mobile.
I am using version 2 of jfxmobile-plugin to cross-compile for mobile, which uses gluonvm:

org.javafxports:jfxmobile-plugin:2.0.29

Does javafxports in general support FXML Script Event Handlers on iOS and/or Android?

I am trying following fxml file, which works on desktop, on Android and iOS:

<?xml version="1.0" encoding="UTF-8"?>
<?language javascript?>
...
<Button fx:id="button" onMouseClicked="label.setText('Button has been clicked from JavaScript');" text="%button.text" />

On Android and iOS I get following exception:

System.err(19642): Exception in Application start method
System.out(19642): QuantumRenderer: shutdown
System.err(19642): java.lang.reflect.InvocationTargetException
System.err(19642):  at java.lang.reflect.Method.invoke(Native Method)
System.err(19642):  at java.lang.reflect.Method.invoke(Method.java:372)
System.err(19642):  at javafxports.android.DalvikLauncher$1.run(DalvikLauncher.java:188)
System.err(19642):  at java.lang.Thread.run(Thread.java:818)
System.err(19642): Caused by: java.lang.RuntimeException: Exception in Application start method
[MALI][Gralloc](193): [+]hnd:0x7fb884c000, fd:27, ion_hnd(0x4), req_format(0x1), int_fmt(0x1)  byte_stride(3200), flags(0x4), usage(0xb00), size(3788800), alloc_size(3788800) 800(800)X1184(1184) pid(193)  sec (0)
System.err(19642):  at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
System.err(19642):  at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$138(LauncherImpl.java:182)
System.err(19642):  at com.sun.javafx.application.LauncherImpl.access$lambda$1(LauncherImpl.java)
System.err(19642):  at com.sun.javafx.application.LauncherImpl$$Lambda$2.run(Unknown Source)
System.err(19642):  ... 1 more
System.err(19642): Caused by: javafx.fxml.LoadException: Error resolving onMouseClicked='label.setText('Button has been clicked from JavaScript');', either the event handler is not in the Namespace or there is an error in the script.
System.err(19642): file:/data/app/com.indsp.software.playground.javafxmobiledemo.demoapp-1/base.apk!/com/indsp/software/playground/javafxmobiledemo/demoapp/scenes/Scene1.fxml:46
HAL(19642): loaded HAL id=gralloc path=/system/lib/hw/gralloc.mt8163.mali.so hmi=0x0 handle=0xf46f9154
[MALI][Gralloc](19642): [+]r_hnd:0xf7a2e728, fd:44, ion_hnd(0x4), req_format(0x1), int_fmt(0x1)  byte_stride(3200), flags(0x4), usage(0xb00), size(3788800), alloc_size(3788800) 800(800)X1184(1184) pid(19642)  sec (0)
Kernel(193): [371573.005712] <2> (2)[236:Binder_1][name:ion_mm_heap&][ION][ion_dbg] alloc_pages order=2 cache=0
System.err(19642):  at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2597)
System.err(19642):  at javafx.fxml.FXMLLoader.access$100(FXMLLoader.java:103)
System.err(19642):  at javafx.fxml.FXMLLoader$Element.processEventHandlerAttributes(FXMLLoader.java:610)
System.err(19642):  at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:770)
System.err(19642):  at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2823)
System.err(19642):  at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2532)
System.err(19642):  at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
System.err(19642):  at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
System.err(19642):  at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
System.err(19642):  at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
System.err(19642):  at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
System.err(19642):  at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3116)
System.err(19642):  at com.indsp.software.playground.javafxmobiledemo.demoapp.DemoApp.start(DemoApp.java:21)
System.err(19642):  at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$145(LauncherImpl.java:863)
System.err(19642):  at com.sun.javafx.application.LauncherImpl.access$lambda$8(LauncherImpl.java)
System.err(19642):  at com.sun.javafx.application.LauncherImpl$$Lambda$9.run(Unknown Source)
System.err(19642):  at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$158(PlatformImpl.java:326)
System.err(19642):  at com.sun.javafx.application.PlatformImpl.access$lambda$6(PlatformImpl.java)
System.err(19642):  at com.sun.javafx.application.PlatformImpl$$Lambda$7.run(Unknown Source)
System.err(19642):  at com.sun.javafx.application.PlatformImpl.lambda$null$156(PlatformImpl.java:295)
System.err(19642):  at com.sun.javafx.application.PlatformImpl.access$lambda$18(PlatformImpl.java)
System.err(19642):  at com.sun.javafx.application.PlatformImpl$$Lambda$19.run(Unknown Source)
System.err(19642):  at java.security.AccessController.doPrivileged(AccessController.java:52)
System.err(19642):  at com.sun.javafx.application.PlatformImpl.lambda$runLater$157(PlatformImpl.java:294)
System.err(19642):  at com.sun.javafx.application.PlatformImpl.access$lambda$5(PlatformImpl.java)
System.err(19642):  at com.sun.javafx.application.PlatformImpl$$Lambda$6.run(Unknown Source)
System.err(19642):  at com.sun.glass.ui.monocle.RunnableProcessor.runLoop(RunnableProcessor.java:93)
System.err(19642):  at com.sun.glass.ui.monocle.RunnableProcessor.run(RunnableProcessor.java:52)
System.err(19642):  ... 1 more

Solution

  • Based on the error you get:

    ...either the event handler is not in the Namespace or there is an error in the script.

    you can look for the printed message at the FXMLLoader class, and you will find:

    if (handlerName.length() == 0 || scriptEngine == null) {
        throw constructLoadException("Error resolving " + attribute.name + "='" + attribute.value
             + "', either the event handler is not in the Namespace or there is an error in the script.");
    }
    
    eventHandler = new ScriptEventHandler(handlerName, scriptEngine);
    

    So it might seem that there is no scriptEngine.

    To confirm that, you can try to run a simple test on desktop and mobile:

    ScriptEngineManager manager = new ScriptEngineManager();
    if (manager != null) {
        for (ScriptEngineFactory factory : manager.getEngineFactories()) {
            System.out.println("factory: " + factory.getEngineName() + " " + factory.getLanguageName() + " " + factory.getExtensions());
        }
    }
    

    While on Desktop it prints:

    Oracle Nashorn ECMAScript [js]
    

    on mobile (both Android and iOS), it doesn't print anything.

    So this confirms that Script Event Handlers are not supported on mobile.

    On a personal note, I'm not fond of using them on desktop anyway.