How can I use a JavaFX activity in an Android proj

2020-02-14 11:10发布

问题:

I'm trying to run the javafxports sample project Kokos as I want to use JavaFX components in an app built in Android Studio but can't get it to build properly, I can build all other samples but this mixed approach isn't working.

When I build I just get a black screen and the error "java.lang.ClassNotFoundException: Didn't find class "org.javafxports.kokos.Main" on path: DexPathList[[zip file "/data/app/org.javafxports.kokos-2/base.apk"]"

As far as I can tell, none of the kokos classes are actually built into the apk hence why it can't find them, but I can't work out why and this is the only sample I can find of this approach.

Is anyone able to successfully build and run the Kokos sample and if so, did it require any modification?

Alternatively is there another example of using JavaFX components in an Android project like this that I could use as a basis? I just want to be able to have an app consisting of native Android activities but with the ability to launch into a JavaFX activity.


The error message given is:

02-01 21:43:16.406 17575-17575/org.javafxports.kokos V/DalvikLauncher: Launch JavaFX application on DALVIK vm.
02-01 21:43:16.409 17575-17575/org.javafxports.kokos V/DalvikLauncher: We have JavaFX on our current (base) classpath, registered exit listener
02-01 21:43:16.410 17575-17575/org.javafxports.kokos E/DalvikLauncher: Launch failed with exception.
                                                                       java.lang.ClassNotFoundException: Didn't find class "org.javafxports.kokos.Main" on path: DexPathList[[zip file "/data/app/org.javafxports.kokos-1/base.apk"],nativeLibraryDirectories=[/data/app/org.javafxports.kokos-1/lib/arm, /data/app/org.javafxports.kokos-1/base.apk!/lib/armeabi, /vendor/lib, /system/lib]]
                                                                           at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
                                                                           at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
                                                                           at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
                                                                           at javafxports.android.DalvikLauncher.resolveApplicationClass(DalvikLauncher.java:262)
                                                                           at javafxports.android.DalvikLauncher.launchApp(DalvikLauncher.java:164)
                                                                           at javafxports.android.FXDalvikEntity.getLauncherAndLaunchApplication(FXDalvikEntity.java:162)
                                                                           at javafxports.android.FXDalvikEntity.surfaceCreated(FXDalvikEntity.java:304)
                                                                           at android.view.SurfaceView.updateWindow(SurfaceView.java:583)
                                                                           at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:177)
                                                                           at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:944)
                                                                           at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2063)
                                                                           at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1115)
                                                                           at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6023)
                                                                           at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
                                                                           at android.view.Choreographer.doCallbacks(Choreographer.java:670)
                                                                           at android.view.Choreographer.doFrame(Choreographer.java:606)
                                                                           at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
                                                                           at android.os.Handler.handleCallback(Handler.java:739)
                                                                           at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                           at android.os.Looper.loop(Looper.java:148)
                                                                           at android.app.ActivityThread.main(ActivityThread.java:5461)
                                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                                                           at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:102)
                                                                        Suppressed: java.lang.ClassNotFoundException: Didn't find class "org.javafxports.kokos.Main" on path: DexPathList[[dex file "/data/dalvik-cache/xposed_XResourcesSuperClass.dex"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
                                                                           at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
                                                                           at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
                                                                           at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
                                                                                ... 23 more
                                                                            Suppressed: java.lang.ClassNotFoundException: org.javafxports.kokos.Main
                                                                           at java.lang.Class.classForName(Native Method)
                                                                           at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
                                                                           at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
                                                                           at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
                                                                                    ... 24 more
                                                                        Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
02-01 21:43:16.411 17575-17575/org.javafxports.kokos V/FXEntity: Called Surface changed [1080, 1848], format 4
02-01 21:43:16.411 17575-17575/org.javafxports.kokos V/FXActivity native: [JVDBG] SURFACE created native android window at 0xa47cd508, surface = 0xff9d0f60
02-01 21:43:16.412 17575-17575/org.javafxports.kokos V/FXEntity: Called Surface redraw needed
02-01 21:43:16.423 17575-17575/org.javafxports.kokos V/FXEntity: Called Surface redraw needed
02-01 21:43:16.441 1378-1536/system_process I/ActivityManager: Displayed org.javafxports.kokos/javafxports.android.FXActivity: +330ms

Here is my app/build.gradle file, I've tried to update the dependencies but still am having issues, is there anything obviously wrong?


My original app/build.gradle file:

buildscript {
    repositories {
        jcenter()
    }   
    dependencies {
        classpath 'me.tatarka:gradle-retrolambda:3.5.0'
        classpath 'com.android.tools.build:gradle:2.2.3'
    }
}
repositories { 
    jcenter()
}
apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    // minSdkVersion 16
    buildToolsVersion "23.0.2"
    dexOptions {
        preDexLibraries = false
    }
    defaultConfig {
        applicationId "lodgon.org.kokos"
        minSdkVersion 16
        targetSdkVersion 16
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }
    sourceSets {
        main {
            jniLibs.srcDir file("/opt/dalvik-sdk/rt/lib")
            assets.srcDirs = ['assets']
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile fileTree(include: ['*.jar'], dir: '/opt/dalvik-sdk/rt/lib/ext')
}


project.tasks.withType(com.android.build.gradle.tasks.Dex) {
    additionalParameters=['--core-library']
}

My edited app/build.gradle

I applied some suggested fixes, and changed the applicationID and dalvik-sdk location but am still having the same issue, file now looks like this:

buildscript {
    repositories {
        jcenter()
    }   
    dependencies {
        classpath 'me.tatarka:gradle-retrolambda:3.5.0'
        classpath 'com.android.tools.build:gradle:2.2.3'
    }
}
repositories { 
    jcenter()
}
apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    // minSdkVersion 16
    buildToolsVersion "23.0.2"
    dexOptions {
        preDexLibraries = false
    }
    defaultConfig {
        applicationId "javafxports.org.kokos"
        minSdkVersion 16
        targetSdkVersion 16
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }
    sourceSets {
        main {
            jniLibs.srcDir file("C:\\Users\\AdamL\\.gradle\\caches\\modules-2\\files-2.1\\org.javafxports\\dalvik-sdk\\8.60.8\\6630ec66e4703c910ac3fd6151a8494c8b59186b\\unpacked\\dalvik-sdk\\rt\\lib")
            assets.srcDirs = ['assets']
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile fileTree(include: ['*.jar'], dir: 'C:\\Users\\AdamL\\.gradle\\caches\\modules-2\\files-2.1\\org.javafxports\\dalvik-sdk\\8.60.8\\6630ec66e4703c910ac3fd6151a8494c8b59186b\\unpacked\\dalvik-sdk\\rt\\lib\\ext')
}


project.tasks.withType(com.android.build.gradle.tasks.Dex) {
    additionalParameters=['--core-library']
}

Android manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="javafxports.org.kokos" >

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="javafxports.org.kokos.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Theseare the changes I've made from the downloaded sample project

  • JavaFXPorts plugin changed to version 1.32
  • Changed android-gradle plugin references to version 2.2.3
  • Changed retrolamba version to 3.5.0
  • Changed applicationID to correct one
  • Changed dalvik-sdk location to correct one

The build is being run from the containing samples project like: gradlew :Kokos:androidInstall

回答1:

There are several problems on your build.gradle file.

The application id is wrong, you should use the package name:

defaultConfig {
    applicationId "javafxports.org.kokos"
    ...
}  

The dalvik-sdk path is incorrect. The one you have (/opt/dalvik-sdk) is Linux based.

If you have tried the other JavaFXPorts samples, you will have already downloaded a recent version of the dalvik-sdk, and it will be installed in the .gradle repository.

You will find it under:

C:\Users\<user>\.gradle\caches\modules-2\files-2.1\org.javafxports\dalvik-sdk\8.60.8\<id>\unpacked\dalvik-sdk

Find the right path and replace it in both sourceSets (jniLibs.srcDir) and dependencies.



回答2:

In case this is helpful to anyone else, I found out what was wrong in my case.

The samples project readme file suggests you should be able to run the project from the root samples project like the other projects using `gradlew :Kokos:androidInstall- or at least it doesn't claim otherwise. This is NOT how I had success running the project.

To run this project, open just the Kokos project and use gradlew installDebug

Additionally I updated my dependencies, Davik SDK location (as Jose Pereda suggested) and changed the way the core-library flag was set in gradle to replace the old way:

dexOptions {
    ...
    additionalParameters=[ '--core-library']
    ...
}