Friends of OpenJDK Today

How to Create Mobile Apps with JavaFX (Part 1)

June 11, 2021


  • Gail Anderson

    Gail is a Java Champion and Oracle Groundbreaker Ambassador. She is Director of Research and founding member of the Anderson Software Group, a leading provider of training courses in Java, ... Learn more

Mobile application offerings for both IOS and Android continue increasing each year.

In this three-part series, I’ll show how to use JavaFX for mobile app development: JavaFX looks great and runs on both mobile platforms.

You use the same JavaFX code targeting Google Play and Apple App stores. Performance is excellent and startup time is fast with native images. You use Java 11+ and the latest JavaFX.

Our game is TiltMaze Labyrinth. Figure 1 shows TiltMaze running on an Android Nexus 5X. Figure 2 shows TiltMaze running on an iPhone 8 Plus.

Figure 1. TiltMaze on Android
TiltMaze on iPhone
Figure 2. TiltMaze on iPhone

We’ll discuss TiltMaze in three parts. First, we explore the JavaFX code: the basic structure of an animation-type app and the Gluon Attach API that lets you access hardware-specific features in a device-agnostic way.

In Part 2, we’ll discuss the technologies we use with JavaFX to build the three target applications: “regular” JVM, native iOS image, and native Android image. We’ll include the tools and development requirements needed for each target.

Lastly in Part 3, we’ll discuss how to upload this application to the respective mobile app stores.

TiltMaze Labyrinth

Let’s start with the end result first. TiltMaze Labyrinth is a mobile game you can install from both the Apple App Store and Google Play. Download TiltMaze here on your mobile device or tablet to play.

Apple Store download TiltMaze
Google Play download TiltMaze

The game is simple enough: you navigate a rolling ball through a maze within the given time allotment while avoiding strategically placed holes. As you tilt the phone or tablet, the application reads the device’s accelerometer sensor and moves the ball based on the reading. 

The Novice-Expert slider controls how fast the ball rolls and the time allotment for completing the maze. As your skill improves, you can challenge your dexterity by making the ball movements more sensitive while simultaneously decreasing the time allotment.


I am a big proponent of using FXML (FX markup language) to describe your JavaFX views.  To those not familiar with JavaFX, FXML is an XML-based markup language that lets you describe a UI scene.

A free tool, Scene Builder, enables drag-and-drop UI design that produces FXML. FXML helps keep your UI separate from your business logic and application control. You can download Scene Builder from Gluon here. We used FXML to build the TiltMaze UI.

Part of the appeal of this mobile application is its simplicity. TiltMaze is a single-view game. It does not require any cloud data, user sign-ins, complicated menus, or multiple views. The UI is the application and standard JavaFX creates the animations that power the game. You can access the JavaFX source code for TiltMaze on GitHub here:

Note that we removed sensitive licensing and credential information from the project!

The Accelerometer

The accelerometer is a sensor that measures velocity changes in three dimensions: horizontally, vertically, and up-down movements (that include the effects of gravity).

We ignore the up-down movements (or the Z-axis) and respond only to changes in the X-axis and Y-axis.

The coordinate system for the accelerometer matches the JavaFX coordinate system for the X-axis, where values increase from left to right. For the Y-axis, however, the accelerometer coordinate system is opposite. In JavaFX, the origin for the Y-axis is at the top and numbers increase as you move towards the bottom of the screen.

The accelerometer is very sensitive; in fact, it’s difficult to hold a phone or tablet in your hand, remaining as motionless as possible, and not see readings change. The good news is that you sample readings in an Animation loop and use these values to update an object in the XY-coordinate space. You multiply the Y-axis reading by -1 so that it conforms to the JavaFX coordinate system.

Gluon’s offerings include the Attach API that lets you access the various hardware features of typical mobile devices and tablets. Both Apple IOS and Android devices have accelerometers. Here’s how to access the accelerometer in your JavaFX mobile application.

try {
    service = AccelerometerService.create().get();
    System.out.println("Got accelerometer service.");
} catch (Exception e) {
    // No accelerometer, using mouse events.
    System.out.println("No accelerometer service.");
         . . . 

Once you have the AccelerometerService initialized, you can start and stop it, depending on whether the game is in progress.

// start the accelerometer service
// stop the accelerometer service

The TiltMaze game lets you control a rolling ball by tilting the phone. As you tilt the phone left or right, the game moves the ball along the X-axis by updating the translateX property of the ball.

Similarly, as you tilt the phone vertically, the game moves the ball along the Y-axis by updating its translateY property. Since the accelerometer measures changes in velocity, these readings let you simulate a rolling ball by updating the ball’s position. While the game is playing, we read the accelerometer in an Animation loop, as follows.

acceleration = service.getCurrentAcceleration();
xv = acceleration.getX();
yv = acceleration.getY() * -1;

Using these values, we check for possible collisions or falling into holes before updating the ball’s XY position.

ball.setTranslateX(ball.getTranslateX() + xv);
ball.setTranslateY(ball.getTranslateY() + yv);

As the ball rolls, we also mark its path by updating a JavaFX Path object, adding a LineTo segment to the path with each update.

        new LineTo(ball.getTranslateX(), ball.getTranslateY()));

Figure 3 shows a game in progress. The ball’s path is marked in blue and the countdown timer has 6.5 seconds remaining.  Of course, the game must perform collision detection with the maze barriers, holes, and outside boundaries. We leave this code for you to digest at your leisure!

Figure 3. TiltMaze during play

The Novice/Expert slider is disabled during play, but can be adjusted between games. The Novice setting has the longest game time and the slowest ball roll. The Expert setting corresponds to the shortest game time and the fastest ball roll. And you can experiment with values in between that fit your level.

Scaling to Device Size

Although mobile devices are generally similar in that they’re portrait-mode rectangles, their sizes can vary quite a bit. We scale the maze so that the aspect ratio is constant and fits within the device’s form factor.

We compute a scale factor, using the resulting scale factor to build the maze’s predefined barriers, boundaries, and holes.

We limit orientation for the game for portrait mode only. If you reorient your device, the application stays in portrait mode.

Mouse Events

The edit-compile-install-run cycle is relatively long for native targets. Therefore, we simulate the maze program on a desktop to test the JavaFX UI as much as possible before installing it on a mobile device. We use mouse events instead of the accelerometer to guide the ball through the maze.

Although this is really a poor imitation of an accelerometer, it provides a convenient environment for testing the UI: the progress indicator, the Novice/Expert slider, and the Start/Stop game button.


We installed the TiltMaze application on an iPhone 8 Plus and an Android Nexus 5X.

The iPhone model is a newer and faster device, but both targets perform the ball roll smoothly with no issues.

The GraalVM-Gluon build creates images that run natively on the target devices.


In Part 2, we show you how to build and install TiltMaze on a locally connected iPhone and Android device.


Related Articles

View All
  • How to Create Mobile Apps with JavaFX (Part 2)

    In Part 1, we introduced a mobile app game, TiltMaze, written completely in JavaFX, which you can download from either the Apple App Store or Google Play and install it on your mobile device or tablet.

    In this article, we’ll discuss the technologies we use with JavaFX to build the JVM byte code version as well as native images that target iOS and Android devices.

    Read More
    June 18, 2021
  • How to Create Mobile Apps with JavaFX (Part 3)

    In Part 1, we introduced a mobile app game, TiltMaze, written completely in JavaFX, which you can download from either the Apple App Store or Google Play and install it on your mobile device or tablet.

    In Part 2, we showed you how to work with Gluon and GraalVM to build native images that execute on either Apple or Android mobile devices and tablets.

    In this article, we’ll discuss how to upload your application to the respective mobile app stores so the world can install your application on their devices.

    Read More
    June 25, 2021
  • Virtual Foojay OpenJDK 17+ JUG Tour

    To celebrate OpenJDK 17 and as a community platform for its users, we’re kicking off the Virtual Foojay OpenJDK 17+ JUG Tour. Ari Waller, JFrog’s Event Manager, well known to many JUGs, will continue to wear a second hat—that of Foojay Event Manager.

    During September and October, contributors to Foojay will be making a whistle stop tour through as many JUGs as possible, via their virtual meetups! (And if you’re not holding virtual events or don’t have the facilities for this, we can support by making these available as needed.)

    Read More
    Avatar photo
    Avatar photo
    Jadon Ortlepp profile
    July 21, 2021


  • Gail Anderson

    Gail is a Java Champion and Oracle Groundbreaker Ambassador. She is Director of Research and founding member of the Anderson Software Group, a leading provider of training courses in Java, ... Learn more

Comments (8)

Your email address will not be published. Required fields are marked *

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Save my name, email, and website in this browser for the next time I comment.

Avatar photo
Almas Baimagambetov

Awesome stuff! Great use of `AccelerometerService` API to showcase what JavaFX can do on mobile.

Hallvard Trætteberg

Great to show students, who use JavaFX and FXML to make apps of similar complexity in two university courses I run! I have demonstrated this for them with an app of my own (simple todo-list), but the “last mile” i.e. deploying it to an actual device is in general too tricky for them. E.g. installing the Android dev. kit, connecting a device and running it isn’t trivial, and the setup for iOS seems more complex.

A more specific comment on part 1: I wonder why you use translateX/Y and not layoutX/Y for the ball’s position? My impression is that translateX/Y in general should be used for temporarily rendering a node with an offset e.g. during drag’n drop, not its “stable” location? I guess it doesn’t really matter if the ball isn’t managed by a pane’s layout logic, but still I’d use layoutX/Y for this.

Carl Dea

Nice work!
I look forward to the second part. For the assets and icons for iOS how did you create all icon the sizes?

Gail Anderson

Hi Carl,
I used: — generates a set of icons from a single 1024 x 1024 PNG file. I created the icon image using Inkscape. (From Part 2 🙂

Building With Micronaut, Quarkus, and Spring Boot - Sale123

[…] recent years to make JavaFX apps work on iOS and Android using GraalVM. See Gail Anderson‘s Creating Mobile Apps with JavaFX – Part 1 to learn more about this emerging […]

Nikolay Artamonov

Thank you, great article. Are demonstrated Gluon technologies free to use or need to buy licence?

Gail Anderson

Hi Nikolay,
Everything is free to test out. Gluon Mobile (nicely skinned mobile controls) will require a license to get rid of nag screen. Gluon Mobile is not required for a mobile app and the plugins plus GraalVM can be freely used. But, for serious developers, you should consider a license. Gluon Mobile is priced per developer with no royalties or hidden fees. Gluon also has really nice Cloud and Enterprise products as well as JavaFX long term support.

How can I run Java on iOS? And JavaFX? - Tutorial Guruji

[…] The code for Android and iOS is mostly identical. This tutorial may get you […]

Subscribe to foojay updates:
Copied to the clipboard