So erstellen Sie eine plattformübergreifende mobile App in Java

Wussten Sie, dass Sie mit Java plattformübergreifende mobile Apps erstellen können? Ja, kneif dich, du hast das gleich beim ersten Mal richtig gelesen! Ich werde Ihnen die Grundlagen beibringen, wie Sie mit Ihrem vorhandenen Java-Wissen in 12 einfachen Schritten performante Apps auf Android und iOS erstellen können. Wir werden dies alles mit JavaFX als GUI-Toolkit tun.

Aber zuerst noch etwas mehr Vordergrund. Sie müssen die nachfolgenden Anforderungen erfüllen zu können , eine Anwendung für den Bau sowohl Android und iOS. Wenn Sie jedoch keine iOS-Anwendung erstellen möchten, können Sie diese auf jedem x64-Bit-Computer entwickeln, der Java SE 8 unterstützt. Dieses Projekt ist ein mit gradle erstelltes Git-Repository. Sie müssen jedoch kein Git-Repository erstellen.

Folgendes sind die Anforderungen :

  • Eine JDK 1.8-konforme JVM
  • Android-Befehlszeilentools (SDK v.27)
  • XCode 9.2
  • Gradle 4.2
  • Git Large File Storage (v.2.5.0) (Nicht erforderlich, wenn Sie kein Git-Repository erstellen möchten)
  • Vorzugsweise mindestens 4G RAM

Ungeduldig? Möchten Sie ein Endergebnis sehen? Schauen Sie sich das abgeschlossene Projekt unten an.

afinlay5 / OnyxFx

Gradle-Quellcode-Repository für OnyxFx, ein plattformübergreifendes (Android / iOS / Linux / macOS / Windows) JavaFX-App-Rendering… github.com

Meine Entwicklungsumgebung wird Fedora Linux 28 und macOS High Sierra sein. Jetzt, wo wir das aus dem Weg haben, wollen wir uns vertiefen.

1) Erstellen Sie einen Ordner für das Projekt

Ich habe mein Projekt OnyxFx wie folgt gehostet: " / home / adriandavid / Projects / OnyxFx". Es steht Ihnen natürlich frei, das Projekt zu hosten, wo immer Sie möchten.

2) Initialisiere gradle, Git, setze JAVA_HOME

Öffnen Sie ein Terminal im Stammverzeichnis des Projektverzeichnisses. Wenn gradle richtig konfiguriert ist, sollte nach dem Ausführen des folgenden Befehls Folgendes angezeigt werden:

gradle -v

Sie müssen sicherstellen, dass gradle Ihre Java Development Kit (JDK) 8-Installation neben dem Abschnitt mit der Bezeichnung „JVM“ auflistet.

Es gibt viele Möglichkeiten, dies zu tun. Am einfachsten ist es jedoch, sicherzustellen, dass Ihre Umgebungsvariable JAVA_HOME richtig eingestellt ist.

Abhängig von Ihrer Umgebung gibt es viele Möglichkeiten, dies zu tun. Eine Möglichkeit, dies in den meisten * nix-Umgebungen zu tun, besteht darin, die Variable in der Datei /home//.b ash rc oder / etc / pro festzulegen . Lesen Sie das Handbuch Ihres Betriebssystems, um sicherzustellen, dass Ihre Umgebungsvariable JAVA_HOME richtig eingestellt ist.

Sie können die folgenden Zeilen am Ende von .bashrc oder profile einfügen, um sicherzustellen, dass JAVA_HOME korrekt eingestellt ist.

JAVA_HOME=/home/adriandavid/java/oracle_jdk1.8.0_181/export JAVA_HOME

Hinweis: Hier können Sie Oracle JDK 8 installieren.

Stellen Sie dann sicher, dass die Shell die obigen Änderungen widerspiegelt, indem Sie einen der folgenden Befehle ausführen:

source ~/.bashrcsource /etc/profile

Geben Sie den folgenden Befehl ein, um zu überprüfen, ob die Variable richtig eingestellt ist:

echo $JAVA_HOME

Wenn Sie immer noch Probleme haben oder Microsoft Windows verwenden, lesen Sie hier.

Führen Sie zunächst git initdas Stammverzeichnis des Projekts aus, um das Git-Repository zu initialisieren. Hinweis: Wenn Sie kein Git-Repository hosten möchten, können Sie diesen Schritt überspringen.

Führen Sie gradle initzweitens das Stammverzeichnis des Projekts aus, um das Gradle-Repository zu initialisieren. Dieser Schritt ist erforderlich.

Hinweis: Sie werden feststellen, dass mein Beispiel etwas anders aussieht. Dies liegt daran, dass ich Gradle und Git bereits in meiner lokalen Umgebung initialisiert habe.

3) Werde groovig! Bearbeiten Sie gradle.build und

Hoffentlich können Erde, Wind und Feuer dir helfen, groovig zu werden! Schalten Sie Ihren bevorzugten Texteditor ein, bearbeiten Sie Ihre build.gradle im Stammverzeichnis Ihres Projekts und ersetzen Sie den Inhalt durch den Inhalt des folgenden GitHub-Inhalts.

Diese build.gradle-Einstellungen konfigurieren unser gradle-Projekt so, dass es das javafxmobile- Plugin verwendet, das das Arbeitspferd unseres Projekts ist. Mehr über das Plugin erfahren Sie hier und hier. Unter anderem automatisiert das javafxmobile-Plugin das Herunterladen (von Maven Central oder jcenter) und das Hinzufügen der iOS- und Android-SDKs zum Klassenpfad Ihrer Anwendung.

Wenn Sie mit Gradle, Maven oder Ameise vertraut sind, haben Sie wahrscheinlich eine Vorstellung davon, was los ist. Wenn Sie mit Gradle nicht vertraut sind, machen Sie sich darüber keine Sorgen . Alles, was Sie verstehen müssen, ist, dass gradle ein Build-Tool ist, mit dem viele Aufgaben beim Erstellen von Apps automatisiert werden können, z. B.: Abrufen von Abhängigkeiten, Projektorganisation usw.

Beachten Sie, dass wir auf Android 7.1 Nougat (API-Version 25) und iOS 11 abzielen (wir werden sehen, wo dies in Kürze geschieht). Sie können diese Werte nach Belieben anpassen. Beachten Sie jedoch, dass Sie im Fall von Android sicherstellen müssen, dass die API-Version mit der Version des SDK übereinstimmt, das Sie heruntergeladen haben (dazu später mehr).

Zuletzt werde ich in diesem Tutorial die Produktion signierter ausführbarer Dateien nicht demonstrieren. Aus diesem Grund ist iOSSkipSigning auf true gesetzt und wir verwenden die GradA-Task releaseAndroid nicht. Sie können jedoch die entsprechenden Unterkünfte bereitstellen, um signierte Apps zu erstellen.

4) Erstellen Sie eine neue Datei mit dem Namen gradle.properties und konfigurieren Sie sie

Erstellen Sie eine neue Datei im Stammverzeichnis des Projekts mit dem Namen gradle.propertiesund fügen Sie der Datei den folgenden Inhalt hinzu.

robovm.device.name=iPhone-7robovm.sdk.version=11.0org.gradle.jvmargs=-Xms4g -Xmx8g

These settings tell the javafxports plugin to use an iPhone-7 as the on-board emulator, to target iOS 11, and to pass the Xms and Xmx flags to the JVM, which specifies both the initial memory pool to 4GB and the maximum heap memory pool to 8GB. This will be necessary for the compilation of the openJDK and the development of the iOS build.

5) Install Homebrew (iOS only)

If you do not have a Mac and are not intending to produce an iOS build, feel free to skip this step.

Open the terminal in macOS and paste the following command.

/usr/bin/ruby -e "$(curl -fsSL //raw.githubusercontent.com/Homebrew/install/master/install)"

6) Install the USB Multiplexing Socket (iOS only)

Only move on to this step if Homebrew has successfully installed. If you do not have a Mac and are not intending to produce an iOS build, feel free to skip this step.

Open the terminal in macOS and paste the following command.

brew install usbmuxd

7) Grab the Android Command Line Tools

Grab Android Command Line Tools for your platform here. After the download has finished, unzip the folder and paste the contents in the directory of your choice. For me, this was /home//Android.

8) Set Android_HOME, Grab necessary Android packages

As with Java, gradle needs to know where to look to find the Android Command Line Tools. There are a few ways to do this. However, in the spirit of simplicity and consistency, we will set the ANDROID_HOME environmental variable in this tutorial. Add the following variable in the same way that we did it for JAVA_HOME. For example:

ANDROID_HOME=/home/adriandavid/Android/ export ANDROID_HOME

Remember to reload the shell by adding source le> as we did for JAVA_HOME.

Now, grab the tools necessary to build the Android build. Execute the following command:

# *.nix./sdkmanager "platform-tools" "build-tools;25.0.3" "platforms;android-25" "extras;android;m2repository" "extras;google;m2repository"
or
#Windowssdkmanager "platform-tools" "build-tools;25.0.3" "platforms;android-25" "extras;android;m2repository" "extras;google;m2repository"

Take careful notice that the SDK and API version we have specified in gradle.build correspond to the version we have specified in this command. Namely, “25”. Should this be misaligned, the build will not succeed.

9) Create the application’s directory structure

To automate the process of creating these directories, execute the following shell script.

Bourne-Again Shell / Korn Shell:

Windows Shell (cmd):

Save the file as mkpdir.bat or mkpdir.sh and execute the file from the project’s root directory as root (or Administrator).

# *.nixchmod +x mkdir.sh-sh ./mkpdir.sh
# Windowsmkpdir

Notice that we created directories for embedded and desktop. We will produce a desktop build, because it takes no additional work to do so. However, we will not produce any builds for embedded devices.

10) Create your JavaFX Application!

Navigate to /src//java and begin developing your JavaFx application! Application resources are stored in /src//resources.

You can start with a simple Hello World application or look at the source code that I have put together here. OnyxFx is an application I made, following these instructions, that makes REST calls over HTTP to the OnyxFxAPI. The API, in turn, is a web scraper that will return the statistical data (points per game, rebounds per game, assists per game) for the NBA® player and season the client specifies. It returns the data as JSON, which is then parsed and displayed to the screen of the mobile app. Feel free to edit it!

Keep in mind that although you can share source code, you should include custom edits in each copy of the source, should you want to make device specific changes.

Also note that the underlying compiler (MobiDevelop’s fork of RoboVM) does not fully support all Java 8 APIs. If you look very closely at my source code, you will notice that in the iOS version of the source code, I have removed unsupported API such as java.util.function.BiConsumer and java.util.Map.replace().

11) Create a RAM disk for iOS builds (iOS only)

The compilation process for iOS is very resource-heavy, as the plugin will compile the entire openJDK and other libraries twice to create a fat JAR that it will use to build your application. Therefore, you should preemptively create a RAM disk to accommodate for the memory requirements.

This step, however, is subject to your judgement of your machine’s capabilities. For context, the macOS machine that I used to compile my iOS app has 4GB of DDR2 RAM. I decided to make an 8GB RAM disk. To do so, execute the following command in the terminal.

SIZE=8192 ; diskutil erasevolume HFS+ ‘RoboVM RAM Disk’ `hdiutil attach -nomount ram://$((SIZE * 8192))`

12) Build and Run your application!

To build your application, execute the gradle wrapper in the root directory from the terminal as follows.

./gradlew clean build

This will produce a desktop application packaged as a JAR with scripts to run the application provided in /build/distributions/ar>; and /build/distributions/Name.zip>. Should you unzip the directories, you will notice the following structure:

Original text


Notice that in /bin there are scripts to execute the application. These scripts rely on preserving the current folder structure. Also notice that is not necessary for you to have tree installed. It is used here simply for illustrative purposes.

There is, additionally, a standalone JAR that you can use to execute the application on any desktop environment supporting JavaFX 8. To run the application, execute one of the following:

# Navigate to /build/distributions//
#On *.nixcd bin./
#On Windowscd bin
#Platform agnosticjava -jar OnyxFxMobile.jar (or double click, if jvm is configured to run .jar files)
Note: If the executable providing "java" is not the same vendor and/or version of the Java 8 JDK with which you built this application, the jar may not run. JavaFX 8 builds between the openJDK & Oracle JDK are incompatible.
Otherwise: /location/to/java8/bin/java -jar 

View this project’s gradle tasks

You can view this project’s gradle tasks by running the following in the project’s root directory.

./gradlew tasks

To Compile, Run on Desktop

The following command will run your project in the host environment.

./gradlew jar./gradlew run

You will find a standalone jar in build/libs/t;.jar .

To Compile, Run on Android

./android #Generates a debug Android apk containing the JavaFX application.
./androidInstall #Launch the application on a connected android device.
./androidRelease #Generates a release Android apk containing the JavaFX application.
Note: You will need to configure a valid signingConfig when releasing an APK (javafxports).

You will find two APKs in build/javafxports/android.

The first will be named t;.apk.

The second will be named -unaligned.apk.

To Compile, Run on iOS

./createIpa - Generates an iOS ipa containing the JavaFX app.
./launchIOSDevice - Launches app on a connected ios device.
./launchIPadSimulator - Launches app on an iPad simulator.
./launchIPhoneSimulator - Launches app on an iPhone simulator.

You will find three executables in build/javafxports/ios.

The first will be named t;.ipa.

The second will be named ame>.dSYM.

The third will be named <AppName>.app.

Some screenshots of my sample app

On Desktop

On Android

On iPhone

On iPad

Splash Screen

My Closing Thoughts

javafxports is a promising project that aims to bring JavaFX and the Java SE platform onto mobile and other devices. In a way, the tool parallels Xamarin in its efforts. However, the project has a lot of work left to be done.

For a start, the plugin currently does not fully support Java 8. On Android, it uses retrolambda to handle Java 8 Lambda Expressions & Method References. It technically is up to Java 6. Additional dependencies make it such that you can use Java 8. However, the process is straightforward, the builds work as expected, and the compilation time is not too long.

On iOS, however, the builds are extremely memory-intensive and the compilation process takes a very long time. The following is a snippet of the log for ./gradlew createIpa task.

:createIpa (Thread[Task worker for ‘:’,5,main]) completed. Took 1 hrs 46 mins 40.198 secs.

In total, the process consumed about over 6GB of RAM on my machine. This is hardly ideal. However, the future is promising. A company called Gluon has developed a high performance, fully modular custom JVM fully supporting Java 9, that you can read more about here.

This article is originally published on the blog section of my homepage, here.

Resources to explore:

  • JavaFxMobile Plugin Git Repo: //github.com/javafxports/javafxmobile-plugin
  • JavaFxPorts Documentation: //docs.gluonhq.com/javafxports/#_how_it_works
  • JavaFxPorts Homepage: //javafxports.org/
  • Gluon Documentation: //gluonhq.com/developers/documentation/
  • Google Groups Page for JavaFxPorts: //groups.google.com/forum/#!forum/javafxports
  • StackOverflow Page for JavaFxPorts: //stackoverflow.com/questions/tagged/javafxports
  • Gluon Mobile Pricing/License Options: //gluonhq.com/products/mobile/buy/