I'm trying to get an application written in JavaFX ported across to Android and for the most part I have been successful in my attempts. In that the application will run on Android after packaging an apk file using Netbeans IDE and Gradle.
But the problem I have is that the application will crash when trying to access a google map through JavaFX Webview component. What I am using is the following in JavaFX:
googleMapEngine.load(getClass().getResource("/googleLondonMap.html").toExternalForm());
And the html file is located under the Resources folder in the Gradle root folder.
When I test the application in Netbeans by right clicking on the Gradle root node and selecting Tasks --> Run --> Run. My application runs perfectly, including accessing the google map using the html file and JavaFX Webview.
The creation of the apk file is also successful in using Tasks --> Android --> Android. But once I install the apk file on an android device and access the google map portion of my application it throws me out of the application saying "Unfortunately has stopped". Any clues on how to fix this?
Looking at the log file created using the adb command I saw the following output:
E/AndroidRuntime( 6038): FATAL EXCEPTION: JavaFX Application Thread
E/AndroidRuntime( 6038): Process: com.SundaeThePugApp, PID: 6038
E/AndroidRuntime( 6038): java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
E/AndroidRuntime( 6038): at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
E/AndroidRuntime( 6038): at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
E/AndroidRuntime( 6038): at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
E/AndroidRuntime( 6038): at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
E/AndroidRuntime( 6038): at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
E/AndroidRuntime( 6038): at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
E/AndroidRuntime( 6038): at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
E/AndroidRuntime( 6038): at javafx.event.Event.fireEvent(Event.java:198)
E/AndroidRuntime( 6038): at javafx.scene.Node.fireEvent(Node.java:8411)
E/AndroidRuntime( 6038): at javafx.scene.control.Button.fire(Button.java:185)
E/AndroidRuntime( 6038): at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
E/AndroidRuntime( 6038): at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
E/AndroidRuntime( 6038): at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
E/AndroidRuntime( 6038): at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
E/AndroidRuntime( 6038): at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
E/AndroidRuntime( 6038): at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
E/AndroidRuntime( 6038): at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
E/AndroidRuntime( 6038): at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
E/AndroidRuntime( 6038): at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
E/AndroidRuntime( 6038): at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
E/AndroidRuntime( 6038): at javafx.event.Event.fireEvent(Event.java:198)
E/AndroidRuntime( 6038): at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
E/AndroidRuntime( 6038): at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
E/AndroidRuntime( 6038): at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
E/AndroidRuntime( 6038): at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
E/AndroidRuntime( 6038): at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
E/AndroidRuntime( 6038): at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
E/AndroidRuntime( 6038): at java.security.AccessController.doPrivileged(AccessController.java:52)
E/AndroidRuntime( 6038): at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$336(GlassViewEventHandler.java:388)
E/AndroidRuntime( 6038): at com.sun.javafx.tk.quantum.GlassViewEventHandler.access$lambda$1(GlassViewEventHandler.java)
E/AndroidRuntime( 6038): at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$4.get(Unknown Source)
E/AndroidRuntime( 6038): at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
E/AndroidRuntime( 6038): at com.sun.javafx.tk.quantum.GlassViewE
Here is the build.gradle file and yes I am using the Verdana font. But the font is coming through OK from what I can see on my android device.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.0.7'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'com.SundaeThePugApp.SundaeThePugFX'
dependencies {
compile 'com.gluonhq:charm:2.1.0'
androidRuntime 'com.gluonhq:charm-android:2.1.0'
iosRuntime 'com.gluonhq:charm-ios:2.1.0'
desktopRuntime 'com.gluonhq:charm-desktop:2.1.0'
}
jfxmobile {
android {
manifest = 'src/android/AndroidManifest.xml'
androidSdk = 'C:/Users/Zermatt/AppData/Local/Android/android-sdk/'
}
}
Edit
Found the cause for the Fatal Exception. It appears Android does not like the following block of code:
URL resource= getClass().getClassLoader().getResource("Music/ThemeMusic.mp3");
themeSong = new MediaPlayer(new Media(resource.toString()));
themeSong.setOnEndOfMedia(new Runnable()
{ public void run()
{ themeSong.seek(Duration.ZERO);
}
});
themeSong.play();
And this block of code comes up with error message in Android:
googleMapEngine.load(getClass().getResource("/googleLondonMap.html").toExternalForm());
Webpage not available: The webpage at jar:file:/data/app/com.SundaeThePugApp - 1/base .apk!/googleLondonMap.html could not be loaded because:
net::ERR_UNKNOWN_URL_SCHEME
so what can I do now to rectify this?
EDIT AGAIN
Experimenting with Jose solution and building upon it, I found a way to get the JavaScript in the Html working although it ain't pretty. Essentially the code he supplied I put into a method (called createAndroidURLScheme) and returned a string. Here is the code and yes it works fine in JavaFX, but not in Androids webview again:
String url = createAndroidURLScheme("/googleTestMap.html");
//System.out.println(url);
googleMapEngine.loadContent(url, "text/html");
googleMapEngine.setJavaScriptEnabled(true);
googleMapEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>()
{ public void changed(final ObservableValue<? extends Worker.State> observableValue, final State oldState, final State newState)
{ if (newState == State.SUCCEEDED)
{ googleMapEngine.executeScript(
"var latlng = new google.maps.LatLng(59.438722, 24.745278);" +
"var myOptions = {" +
"zoom: 15," +
"center: latlng," +
"mapTypeId: google.maps.MapTypeId.ROADMAP," +
"mapTypeControl: false," +
"navigationControl: false," +
"streetViewControl: false," +
"backgroundColor: '#666970'," +
"disableDefaultUI: true" +
"};" +
"" +
"var map = new google.maps.Map(document.getElementById('map_canvas'), myOptions);");
}
}
});
Now through logcat I get this new Android Fatal Exception:
I/System.out( 809): [JVDBG] Error firing event
W/System.err( 809): java.lang.ClassNotFoundException: com.sun.webkit.NativeWebView
W/System.err( 809): at java.lang.Class.classForName(Native Method)
W/System.err( 809): at java.lang.Class.forName(Class.java:309)
W/System.err( 809): at com.oracle.dalvik.InternalWebView._fireLoadEvent(InternalWebView.java:347)
W/System.err( 809): at com.oracle.dalvik.InternalWebView.fireLoadEvent(InternalWebView.java:140)
W/System.err( 809): at com.oracle.dalvik.InternalWebView.access$400(InternalWebView.java:43)
W/System.err( 809): at com.oracle.dalvik.InternalWebView$MyJavaScriptInterface.processHTML(InternalWebView.java:363)
W/System.err( 809): at org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
W/System.err( 809): at org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:39)
W/System.err( 809): at android.os.Handler.dispatchMessage(Handler.java:102)
W/System.err( 809): at android.os.Looper.loop(Looper.java:145)
W/System.err( 809): at android.os.HandlerThread.run(HandlerThread.java:61)
W/System.err( 809): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.sun.webkit.NativeWebView" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
W/System.err( 809): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
W/System.err( 809): at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
W/System.err( 809): at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
W/System.err( 809): ... 11 more
W/System.err( 809): Suppressed: java.lang.ClassNotFoundException: com.sun.webkit.NativeWebView
W/System.err( 809): at java.lang.Class.classForName(Native Method)
W/System.err( 809): at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
W/System.err( 809): at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
W/System.err( 809): at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
W/System.err( 809): ... 12 more
W/System.err( 809): Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
E/AndroidRuntime( 809): FATAL EXCEPTION: JavaFX Application Thread
E/AndroidRuntime( 809): Process: com.SundaeThePugApp, PID: 809
E/AndroidRuntime( 809): java.lang.UnsupportedOperationException: Not supported yet.
E/AndroidRuntime( 809): at com.sun.webkit.WebPage.executeScript(WebPage.java:153)
E/AndroidRuntime( 809): at javafx.scene.web.WebEngine.executeScript(WebEngine.java:860)
E/AndroidRuntime( 809): at com.SundaeThePugApp.SundaeThePugController$1.changed(SundaeThePugController.java:202)
E/AndroidRuntime( 809): at com.SundaeThePugApp.SundaeThePugController$1.changed(SundaeThePugController.java:200)
E/AndroidRuntime( 809): at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
E/AndroidRuntime( 809): at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
E/AndroidRuntime( 809): at javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:176)
E/AndroidRuntime( 809): at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:142)
E/AndroidRuntime( 809): at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
E/AndroidRuntime( 809): at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
E/AndroidRuntime( 809): at javafx.scene.web.WebEngine$LoadWorker.updateState(WebEngine.java:1023)
E/AndroidRuntime( 809): at javafx.scene.web.WebEngine$LoadWorker.dispatchLoadEvent(WebEngine.java:1134)
E/AndroidRuntime( 809): at javafx.scene.web.WebEngine$LoadWorker.access$1000(WebEngine.java:1016)
E/AndroidRuntime( 809): at javafx.scene.web.WebEngine$PageLoadListener.dispatchLoadEvent(WebEngine.java:1003)
E/AndroidRuntime( 809): at com.sun.webkit.WebPage.fireLoadEvent(WebPage.java:251)
E/AndroidRuntime( 809): at com.sun.webkit.NativeWebView$1.run(NativeWebView.java:100)
E/AndroidRuntime( 809): at com.sun.javafx.application.PlatformImpl.lambda$null$155(PlatformImpl.java:295)
E/AndroidRuntime( 809): at com.sun.javafx.application.PlatformImpl.access$lambda$18(PlatformImpl.java)
E/AndroidRuntime( 809): at com.sun.javafx.application.PlatformImpl$$Lambda$19.run(Unknown Source)
E/AndroidRuntime( 809): at java.security.AccessController.doPrivileged(AccessController.java:52)
E/AndroidRuntime( 809): at com.sun.javafx.application.PlatformImpl.lambda$runLater$156(PlatformImpl.java:294)
E/AndroidRuntime( 809): at com.sun.javafx.application.PlatformImpl.access$lambda$5(PlatformImpl.java)
E/AndroidRuntime( 809): at com.sun.javafx.application.PlatformImpl$$Lambda$6.run(Unknown Source)
E/AndroidRuntime( 809): at com.sun.glass.ui.monocle.RunnableProcessor.runLoop(RunnableProcessor.java:92)
E/AndroidRuntime( 809): at com.sun.glass.ui.monocle.RunnableProcessor.run(RunnableProcessor.java:51)
E/AndroidRuntime( 809): at java.lang.Thread.run(Thread.java:818)
V/ApplicationPolicy( 3468): isApplicationStateBlocked userId 0 pkgname com.SundaeThePugApp
V/ApplicationPolicy( 3468): isApplicationStateBlocked userId 0 pkgname com.SundaeThePugApp
V/ApplicationPolicy( 3468): isApplicationStateBlocked userId 0 pkgname com.sec.android.app.launcher
What can I do now to alleviate this and keep Androids Webview happy?
adb logcat -v threadtime
, and look for an exception? Post the relevant part – José Pereda