# JavaFXPorts - Erfahrungen?



## dzim (7. Nov 2016)

Hi zusammen

Ich wollte mich einmal erkundigen, ob es hier bereits Leute gibt, die sich mit JavaFXPorts beschäftigt haben.
Ich hatte vor einiger Zeit schon einmal mit einer sehr frühen Version "gespielt", fand es damals aber noch zu unreif. Jetzt dachte ich mir, ich könnte hier im Büro eines unserer neueren kleineren App-Projekte damit Platformübergreifend aufsetzen, werde aber am Ende wohl nur Android damit entwickeln, da es auf iOS doch noch ein paar issues zu geben scheint (iPhone 5 zeigt 5s schwarzen Bildschirm an - blöd).

Daher meine Frage: Gibt es hier jemanden, der es schon probiert hat? Wenn ja, wie erfolgreich wart ihr damit?

Grüsse,
Daniel

PS: Links:
Gluon (versucht ein Geschäftsmodel drum herauf aufzubauen, unter anderem bieten sie jetzt den SceneBuilder OSS an): http://gluonhq.com
JavaFXPorts selbst: http://gluonhq.com/labs/javafxports/
Doku: http://docs.gluonhq.com/javafxports/
u.s.w.u.s.f. ...


----------



## lam_tr (15. Nov 2016)

Hi dzim,

bist du da weiter gekommen? Ich habe mal das Gluon Eclipse Plug-In angeschaut, scheint ziemlich cool zu sein. Aber das mit dem Gradle built lief nicht erfolgreich.

Außerdem werden die Apps immer mit ein Key versehen, d.h. bevor ich die Anwendung überhaupt starten kann, wird eine Anfrage zum Gluon Server gemacht oder?

Grüße
lam


----------



## dzim (15. Nov 2016)

Ja läuft (mag aber auch eher Maven als Gradle, im Moment). Nein. Es wird nicht "nach Hause telefoniert", aber ein Key wird zum beseitigen des "Nag-Dialogs" benötigt. Wenn man aber keine Scheu hat, sich die Hände "schmutzig" zu machen und auf Material Design verzichten kann (oder wie ich, dessen Designvorgaben MD unmöglich machen, bzw. mich zu sehr eisnchränken), kannst du fast eine normale Anwendung schreiben. Und brauchst keinen Key. OpenSource und so. Es ist nur wichtig, das Höhe und Breite der Stage gleich dem Primary Screen ist, sonst sieht es... blöd... aus. :-D
Kann da bei Gelegenheit/Interesse mal ein Gradle-File vorbereiten, mit dem man was anstellen kann.
Vorausgesetzt: Unter der IDE deiner Wahl idealerweise mal das Gluon-Plugin installieren.


----------



## lam_tr (15. Nov 2016)

Ohja sehr gerne dzim, ich habe die Gluon Plug-In in Eclipse Oxygen installiert. Sollte kein Problem sein. Und Gradle Plug-In ist sowieso schon drauf.

Grüße
lam

P.S. Eine andere Frage ist, beim Bauen werden JavaFX Runtimes (jfxrt.jar = 17mb) eigentlich in die APK inkludiert?


----------



## dzim (15. Nov 2016)

Nein. Jain. Es wird eine spezielle Dalvik-Version des OpenJDKs verwendet, wenn ich mich recht entsinne. Mein (Debug) APK ist im Moment knapp 9MB gross. Nicht gerade klein, zumal ja quasi keine Daten enthalten sind, aber noch nicht so schlimm.
Sei nur darauf gefasst, das die Performance auf bestimmten Geräten (alt, oder Dev-Telefone, deren Speicher arg oft überschrieben wurde) nicht sehr performant läuft. Jedoch mein bisher grösstes Aha-Erlebnis hatte ich auf einem iPhone 6 irgendwas - das ist gerannt, wie ein Tier! War echt beeindruckt. Auf meinem Nexus 5-Dev-Phone geht es so. Ist schon etwas träger, aber noch zu ertragen.


----------



## dzim (16. Nov 2016)

So. Hier mal ein kurzer Abriss, wie ich vorgegangen bin, um die App, an der ich gerade baue, aufzubauen.

Schritt 1: Ich habe ein separates Eclipse aufgesetzt und das Gluon-Plugin installiert (installiert eine nicht ganz aktuelle Version von e(fx)clipse mit, sowie Buildship für Gradle).

Schritt 2: Gluon Mobile Projekt mit FXML View erstellt. Getestet (Gradle task "run" für Desktop, "androidInstall" für... Android). Damit ich "androidInstall" unter der "others"-Kategorie im "Gradle Tasks" View vom Eclipse-Gradle-Plugin "Buildship" im "View Menu" (Pfeil nach unten in der Toolbar) den Haken an "Show All Tasks" setzen.

Schritt 3: Gradle anpassen

```
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.1.1'
    }
}

apply plugin: 'org.javafxports.jfxmobile'

// Nummer Sicher
compileJava.options.encoding = 'UTF-8'
// Nummer Sicher-Sicher
tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

repositories {
    jcenter()
    maven {
        url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
    }
}

// diese sind vor allem für Desktop und iOS wichtig
mainClassName = 'my.package.Main'
preloaderClassName = 'my.package.Preloader'

dependencies {

    // Charm Down - OSS, keine Lizenz nötig
    compile 'com.gluonhq:charm:4.0.1'
    // spezielle Controls, wenn man sie braucht
    compile 'org.controlsfx:controlsfx:8.40.12'
    // Diverse Icon-Fonts. Braucht man immer...
    compile 'de.jensd:fontawesomefx:8.9'

    compile 'com.fasterxml.jackson.core:jackson-databind:2.8.4'

    // versuch, Guice als DI-Framework zu verwenden. Desktop top, Android flopp
    // compile 'com.gluonhq:ignite-guice:1.0.1'

    // aus Doku übernommen, verwende ich als DI nun Afterburner.FX
    // finde es nicht so toll, aber am Ende genügt es mir
    compileNoRetrolambda 'com.airhacks:afterburner.mfx:1.6.2'

    // Zugriff auf die FXActivity
    compile 'org.javafxports:jfxdvk:8.60.8'
    androidRuntime 'org.javafxports:jfxdvk:8.60.8'
}

jfxmobile {
    // für Charm Down plugins bitte die Home Page und das bitbucket-Repo zu Rate ziehen
    // Achtung: Nicht alle Plugins unterstützen alle Plattformen (wieder: Repo zu Rate ziehen)
    downConfig {
        version = '3.0.0'
        plugins 'display', 'lifecycle', 'statusbar', 'storage', 'battery', 'orientation', 'settings', 'browser', 'ble'
    }
    android {
        manifest = 'src/android/AndroidManifest.xml'
        compileSdkVersion = 25
        minSdkVersion = 19
        targetSdkVersion = 25
        dexOptions {
            javaMaxHeapSize '2g'
        }
        // für Jackson...
        packagingOptions {
            pickFirst 'META-INF/LICENSE'
            pickFirst 'META-INF/NOTICE'
        }
    }
    // für iOS bitte immer alle eigenen Packages und so unten eintragen, sonst blöde Fehler
    ios {
        infoPList = file('src/ios/Default-Info.plist')
        forceLinkClasses = [
                'com.gluonhq.**.*',
                'de.jensd.**.*',
                'javax.annotations.**.*',
                'javax.inject.**.*',
                'javax.json.**.*',
                'org.glassfish.json.**.*',
                'my.package.**.*'
        ]
    }
}

task printProps << {
    println System.properties['file.encoding']
}
```

Android Manifest

```
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ch.cnlab.disentis" android:versionCode="1" android:versionName="1.0">
        <supports-screens android:xlargeScreens="true"/>
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.BATTERY_STATS"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
        <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="25"/>
        <application android:label="My App" android:name="android.support.multidex.MultiDexApplication" android:icon="@mipmap/ic_launcher">
                <activity android:name="javafxports.android.FXActivity" android:label="My App"
            android:configChanges="orientation|screenSize" android:screenOrientation="portrait"
            android:hardwareAccelerated="true">
                        <meta-data android:name="main.class" android:value="my.package.Main"/>
                        <meta-data android:name="preloader.class" android:value="my.package.Preloader"/>
                        <meta-data android:name="debug.port" android:value="0"/>
                        <intent-filter>
                                <action android:name="android.intent.action.MAIN"/>
                                <category android:name="android.intent.category.LAUNCHER"/>
                        </intent-filter>
                </activity>
        </application>
</manifest>
```

Und das war's eigentlich schon. Ich hab schon etwas Arbeit in eigene Controls, ein halbwegs gescheites i18n-Framework und DI gesteckt. Ein paar Tipps kann ich dann on-demand noch geben. Dann aber bitte gezielt Fragen.

Grüsse,
Daniel

#edit: Auch auf der Community Edition von IntelliJ getestet, aber ich favorisiere noch immer Eclipse...


----------



## lam_tr (16. Nov 2016)

Boah Daniel, vielen Dank für die Mühe. 

Für Android Entwicklung benutze ich zwar IntelliJ, aber ich denke für JavaFX werde ich lieber bei Eclipse bleiben. Ich bin da auch ein Eclipse Liebhaber 

Ich teste das mal gleich und gib dir dann mal Feedback.

Nochmals Danke!


----------



## lam_tr (16. Nov 2016)

Hi Daniel,

wie bekommst du die APK gebaut? Mit der gradle Datei wird keine APK sondern nur class dateien und abhängikeiten kopiert oder?

Grüße
lam


----------



## dzim (17. Nov 2016)

Das APK liegt in *${project.dir}/build/javafxports/android* - also bei mir jedenfalls. Hat denn *androidInstall* nicht direkt auf das angeschlossene Gerät installiert? Ist der Task erfolgreich gewesen?


----------



## lam_tr (17. Nov 2016)

Moin,

der Run Task ist erfolgreich.
in dem Verzeichnis *${project.dir}/build/javafxports/ *befindet sich bei mir leider nichts. Vor allem finde ich komisch dass ich den Task *androidInstall *nicht habe*.
*
Das Projekt ist als android und Desktop Version erstellt worden.

Liegt es eventuell an meiner Idee oder Gradle Plugin?

Grüße
lam


----------



## dzim (17. Nov 2016)

Habe eine Unterhaltung eröffnet. Damit wir den Thread hier nicht zuspammen...


----------

