Friday Nov 29, 2013

JavaFX on Android multitouch and gestures support

A short entry this week. It looks that I'm on the right path to fix event processing  problems on dalvik, at last. I can't resist to publish short video . The fix hasn't been pushed to repository yet.

Thanks to Pavel Safrata for the sample application.

Friday Nov 22, 2013

Building JavaFX for Android with skia library.

I hope you've tried and succeeded to build JavFX runtime for Android following my blog post How to build OpenJavaFX for Android. Here's a short tweak how to make a freetype library significantly smaller. The result should be functionally identical just instead statically linking freetype of 1.5Mb size we will use on-device library skia. The powerfull skia graphics framework already contains freetype and harfbuzz (complex text layout). Although developers are discouraged to use skia directly since it hasn't public api we could give it a try because the change in build script is very minimal. Every kilobyte matters if you have to repeatedly deploy application to a device.

You will still need freetype headers for compilation but instead libfreetype.a you will use Firstly download from your device.

adb pull /system/lib/ .

Open and edit android.gradle. Go to very bottom and look for ANDROID.fontNativeFreetype.linkFlags and change the name of library to link with. If you've done it like myself e.q. put it along with libfreetype.a to the same directory the script will look like that:

ANDROID.fontNativeFreetype.linkFlags = 
        [linkFlags, "-llog", 
         "-L$freetypeDir/lib", "$freetypeDir/lib/"].flatten()
Now just run build and here we go.

Wednesday Nov 13, 2013

iPack -The iOS Application Packager

iOS applications are distributed in .ipa archive files. These files are regular zip files which contain application resources and executable-s. To protect them from unauthorized modifications and to provide identification of their sources, the content of the archives is signed. The signature is included in the application executable of an.ipa archive and protects the executable file itself and the associated resource files. Apple provides native Mac OS tools for signing iOS executable-s (which are actually generic Mach-O code signing tools), but these tools are not generally available on other platforms. To provide a multi-platform development environment for JavaFX based iOS applications, we ported iOS signing and packaging to Java and created a dedicated ipack tool for it.

The iPack tool can be used as a last step of creating .ipa package on various operating systems. Prototype has been tested by creating a final distributable for JavaFX application that runs on iPad, all done on Windows 7.

Source Code

The source code of iPac tool is in OpenJFX project repository. You can find it in:

<openjfx root>/rt/tools/ios/Maven/ipack

To build the iPack tool use:

rt/tools/ios/Maven/ipack$ mvn package

After building, you can run the tool:

java -jar <path to ipack.jar> <arguments> 

Signing keystore

The tool uses a java key store to read the signing certificate and the associated private key. To prepare such keystore users can use keytool from JDK.

One possible scenario is to import an existing private key and the certificate from a key store used on Mac OS:

To list the content of an existing key store and identify the source alias:

keytool -list -keystore <src keystore>.p12 -storetype pkcs12 -storepass <src keystore password>

To create Java key store and import the private key with its certificate to the keys store:

keytool -importkeystore \
        -destkeystore <dst keystore> -deststorepass <dst keystore password> \
        -srckeystore <src keystore>.p12 -srcstorepass <src keystore password> -srcstoretype pkcs12 \
        -srcalias <src alias> -destalias <dst alias> -destkeypass <dst key password>

Another scenario would be to generate a private / public key pair directly in a Java key store and create a certificate request from it. After sending the request to Apple one can then import the certificate response back to the Java key store and complete the signing certificate entry.

In both scenarios the resulting alias in the Java key store will contain only a single (leaf) certificate. This can be verified with the following command:

keytool -list -v -keystore <ipack keystore> -storepass <keystore password>

When looking at the Certificate chain length entry, the number next to it is 1.

When an executable file is signed on Mac OS, the resulting signature (in CMS format) includes the whole certificate chain up to the Apple Root CA. The ipack tool includes only the chain which is stored under the alias specified on the command line. So to have the whole chain in the signature we need to replace the single certificate entry under the alias with the corresponding full certificate chain.

To do that we need first to create the chain in a separate file. It is easy to create such chain when working with certificates in Base-64 encoded PEM format. A certificate chain can be created by concatenating PEM certificates, which should form the chain, into a single file.

For iOS signing we need the following certificates in our chain:

To convert a certificate from the binary DER format (.der, .cer) to PEM format:

keytool -importcert -noprompt -keystore temp.ks -storepass temppwd -alias tempcert -file <certificate>.cer
keytool -exportcert -keystore temp.ks -storepass temppwd -alias tempcert -rfc -file <certificate>.pem

To export the signing certificate into PEM format:

keytool -exportcert -keystore <ipack keystore> -storepass <keystore password> -alias <signing alias> -rfc -file SigningCert.pem

After constructing a chain from AppleIncRootCertificate.pem, AppleWWDRCA.pem and SigningCert.pem, it can be imported back into the keystore with:

keytool -importcert -noprompt -keystore <ipack keystore> -storepass <keystore password> -alias <signing alias> -keypass <key password> -file SigningCertChain.pem

To summarize, the following example shows the full certificate chain replacement process:

keytool -importcert -noprompt -keystore temp.ks -storepass temppwd -alias tempcert1 -file AppleIncRootCertificate.cer
keytool -exportcert -keystore temp.ks -storepass temppwd -alias tempcert1 -rfc -file AppleIncRootCertificate.pem
keytool -importcert -noprompt -keystore temp.ks -storepass temppwd -alias tempcert2 -file AppleWWDRCA.cer
keytool -exportcert -keystore temp.ks -storepass temppwd -alias tempcert2 -rfc -file AppleWWDRCA.pem
keytool -exportcert -keystore ipack.ks -storepass keystorepwd -alias mycert -rfc -file SigningCert.pem
cat SigningCert.pem AppleWWDRCA.pem AppleIncRootCertificate.pem >SigningCertChain.pem
keytool -importcert -noprompt -keystore ipack.ks -storepass keystorepwd -alias mycert -keypass keypwd -file SigningCertChain.pem
keytool -list -v -keystore ipack.ks -storepass keystorepwd


When the ipack tool is started with no arguments it prints the following usage information:

-appname MyApplication -appid com.myorg.MyApplication    


Usage: ipack <archive> <signing opts> <application opts> [ <application opts> ... ] Signing options: -keystore <keystore> keystore to use for signing -storepass <password> keystore password -alias <alias> alias for the signing certificate chain and the associated private key -keypass <password> password for the private key Application options: -basedir <directory> base directory from which to derive relative paths -appdir <directory> directory with the application executable and resources -appname <file> name of the application executable -appid <id> application identifier Example: ipack MyApplication.ipa -keystore ipack.ks -storepass keystorepwd -alias mycert -keypass keypwd -basedir mysources/MyApplication/dist -appdir Payload/ -appname MyApplication -appid com.myorg.MyApplication    

Tuesday Nov 12, 2013

How to build Open JavaFX for Android.

Here's a short recipe for baking JavaFX for Android dalvik. We will need just a few ingredients but each one requires special care. So let's get down to the business.


The first ingredient is an open JavaFX repository. This should be piece of cake. As always there's a catch. You probably know that dalvik is jdk6 compatible  and also that certain APIs are missing comparing to good old java vm from Oracle.  Fortunately there is a repository which is a backport of regular OpenJFX to jdk7 and going from jdk7 to jdk6 is possible. The first thing to do is to clone or download the repository from Main page of the project says "It works in some cases" so we will presume that it will work in most cases :)
As I've said dalvik vm misses some APIs which would lead to a build failures. To get them use another compatibility repository which is available on GitHub Download the zip and unzip sources into jfx78/modules/base.
We need also a javafx binary stubs. Use jfxrt.jar from jdk8.
The last thing to download are freetype sources from These will be necessary for native font rendering.

Toolchain setup

I have to point out that these instructions were tested only on linux. I suppose they will work with minimal changes also on Mac OS. I also presume that you were able to build open JavaFX. That means all tools like ant, gradle, gcc and jdk8 have been installed and are working all right. In addition to this you will need to download and install jdk7, Android SDK and Android NDK for native code compilation.  Installing all of them will take some time. Don't forget to put them in your path.

export ANDROID_SDK=/opt/android-sdk-linux
export ANDROID_NDK=/opt/android-ndk-r9b
export JAVA_HOME=/opt/jdk1.7.0
export PATH=$JAVA_HOME/bin:$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools:$ANDROID_NDK:$PATH


Unzip freetype release sources first. We will have to cross compile them for arm. Firstly we will create a standalone toolchain for cross compiling installed in ~/work/ndk-standalone-19.
$ANDROID_NDK/build/tools/  --platform=android-19 --install-dir=~/work/ndk-standalone-19

After the standalone toolchain has been created cross compile freetype with following script:

export TOOLCHAIN=~/work/freetype/ndk-standalone-19
export FREETYPE=`pwd`
./configure --host=arm-linux-androideabi --prefix=$FREETYPE/install --without-png --without-zlib --enable-shared
sed -i 's/\-version\-info \$(version_info)/-avoid-version/' builds/unix/
make install

It will compile and install freetype library into $FREETYPE/install. We will link to this install dir later on. It would be possible also to link openjfx font support dynamically against skia library available on Android which already contains freetype. It creates smaller result but can have compatibility problems.


Download patches javafx-android-compat.patch + android-tools.patch and patch jfx78 repository. I recommend to have look at patches. First one android-compat.patch updates openjfx build script, removes dependency on SharedSecret classes and updates LensLogger to remove dependency on jdk specific PlatformLogger. Second one android-tools.patch creates helper script in android-tools. The script helps to setup javaFX Android projects.


Now is time to try the build. Run following script:

gradle -PDEBUG -PDALVIK_VM=true -PBINARY_STUB=~/work/binary_stub/linux/rt/lib/ext/jfxrt.jar \
-PFREETYPE_DIR=~/work/freetype/install -PCOMPILE_TARGETS=android

If everything went all right the output is in build/android-sdk :)

UPDATE: If you want to build without jfxrt.jar binary stub comment out jmx and sample apps from settings.gradle.

Create first JavaFX Android project

Use gradle script int android-tools. The script sets the project structure for you.   Following command creates Android HelloWorld project which links to a freshly built javafx runtime and to a HelloWorld application.

  • NAME is a name of Android project.
  • DIR where to create our first project.
  • PACKAGE is package name required by Android. It has nothing to do with a packaging of javafx application.
  • JFX_SDK points to our recently built runtime.
  • JFX_APP points to dist directory of javafx application. (where all application jars sit)
  • JFX_MAIN is fully qualified name of a main class.
gradle -PDEBUG -PDIR=/home/user/work -PNAME=HelloWorld -PPACKAGE=com.helloworld \
-PJFX_SDK=/home/user/work/jfx78/build/android-sdk -PJFX_APP=/home/user/NetBeansProjects/HelloWorld/dist \
-PJFX_MAIN=com.helloworld.HelloWorld createProject

Now cd to the created project and use it like any other android project. ant clean, debug, uninstall, installd will work. I haven't tried it from any IDE Eclipse nor Netbeans.

Special thanks to Stefan Fuchs and Daniel Zwolenski for the repositories used in this blog post.

JavaFX is a Java GUI toolkit, partially developed from Prague, Czech Republic. The Prague team uses this blog to post articles, code samples and insights about the range of topics the team members specialize in. This includes JavaFX Scenegraph (javafx.scene.*), JavaFX Core libraries & animations, iOS port & Android port.


« November 2013 »