I’d like to start a new series of blog posts focused on Qt on Android.
The first article is about how it began, how it works, the current status, what to expect from 5.2 and what are my plans for 5.3. In the next article I’ll focus on development setup for Android.
Let’s get started:
How did it begin?
In June 2009 I joined ROUTE 66 as a senior Linux developer. My first task was to port the navigation engine on Android. Back then Google hadn’t yet released any NDK officially, so I had to create one of my own from Android sources.
Shortly after, I managed to have a working engine running on Android. I began to love Android but something was missing, something that I cared a lot about. That something was Qt, my favorite framework. That was what was missing! And I said to myself that I had to do something about it.
In October 2009 Nokia (yep, Qt was owned by Nokia back then, what days …) announced the Lighthouse project. The Lighthouse project was created to allow developers to easily port Qt to (almost) any platform.
In late December 2009 (I think it was after Christmas) I had enough free time to begin the port. I also chose to use the Lighthouse project even if it was a very young research project. As far as I know my Android port was the first port that used Lighthouse. Just after a month (in January 2010), I saw the first graphics rendered by Qt on my phone. The feeling was fantastic!
A few months later, after Qt was in a good shape, I began the work on a Qt Creator plugin and on Ministro. The Qt Creator plugin enables the user to manage, develop, deploy, run & debug Qt applications on Android Devices/Emulator very easily.
Even if almost everything was in place, still not too many people wanted to use it because they had to compile everything manually. Then I decided to do something about it.
So, in 2011, a few weeks after Nokia announced their big strategy shift, I announced the first usable SDK for Android. This is how the Necessitas project began and after it become a huge success, I decided to join KDE and to continue the project under the KDE umbrella. Why KDE? Well, because we share the same goal: to keep Qt powerful and free for everyone. Also I could use their fantastic infrastructure to distribute Qt libs.
The very first SDK release was Linux only. Soon Ray Donnelly contacted me and ported the SDK to Windows and Mac. If you are using Necessitas (and Qt5 Android SDK) on any of these platforms, he is the guy you have to thank!
Together with Ray and other people, we’ve managed to do more and more releases of the Necessitas SDK.
Because the Qt Creator plugin was an immense success, I upstreamed the plugin in 2012, when Qt was still owned by Nokia!
In November 2012, I contributed the Android port to Qt Project for Qt 5 integration. Here I’d like to make some clarifications: ONLY Qt 5 is developed under the Qt Project umbrella. Qt 4 is still owned by KDE as Necessitas project.
Let’s see how Qt on Android broadly works. I’m not going to go way too deep in details but enough for you to have an idea how it works.
As I wrote previously, the port is based on the Lighthouse project. Lighthouse (now re-branded as QPA) is the platform abstraction layer for Qt. Basically this layer sits between Qt and the platform, making the porting pretty easy. Because Android applications are written in Java, and it is impossible to connect the Qt event loop to Android’s event loop, I had to move the Qt main event loop to another thread. If you want to extend your application keep in mind the fact that the Qt event loop and Java UI are running on different threads. Even after Google added the NativeActivity, it was impossible to use it, mostly because it didn’t expose all the features we need in Qt.
A Qt for Android application consists of two big parts:
- The native part, containing one or more .so files, which are actually your Qt application. If you choose to bundle Qt libraries, it will contain also these libs.
- Android specific part. This part contains the followings sub-parts:
- Android manifest. This is the entry point of your application. Android uses this file to decide which Application/Activity to start, it contains the application permissions, declares the minimum of the Android API that application needs, etc.
- Two Java classes which load the dependencies and your application. They are also a part of the Java bridge between Qt QPA and the Android world.
- Ministro service .aidl files. These are two interfaces used to communicate with Ministro service. Ministro service is one of the deployment solutions (will write more about that later).
- OIther resources, e.g. assets, strings, images, etc.
All these parts are bundled in a single package which represents your final application. Now lets see how those parts works together.
When your application starts, Android uses the manifest file to run an activity. This activity (which is a custom activity) is a small part of the magic in the Java world of your application. To be able to update Qt libs without breaking the existing application, the Java part is split in two: a very small part which ships together with your application (a part of it) and another part (a Java library, a .jar file) which contains all the logic for the QPA plugin.
The first Java part that is shipped with your application is responsible for finding the missing libs (Qt and Java) and to load them. It also forwards all the events (touch, application states changes, screen changes, etc.) to the second Java part.
The second Java part is responsible for communicating with Qt. It contains all the logic needed by the Android QPA plugin, e.g. the creation and management of the drawing surface, virtual keyboard handling, and so on.
So, the (first) Java part finds and loads all the missing libs and your application and it forwards all the events to the second part, but how does your “main” method get called? Well, the QPA plugin does that. No, I’m not insane! And yes the QPA plugin is loaded before your application starts (actually is loaded even before your application is loaded ).
Ok, let me try and explain why I had to come to such a crazy design.
My dream was to find a way so that the developers could just compile their existing Qt applications for Android, so I had to find a way to call the “main” method (I didn’t want to force you to create other main entry methods for your application, similar to the “WinMain” thing ).
The problem is that in order to call a method from Java, someone has to register that method first, otherwise you can’t call it, here the QPA comes in the scene. After the QPA plugin is loaded, it registers a few native function which are used by the Java part to make calls in the native world. After the Java part finishes to load all the libs and your application, it just calls “startQtApplication“ native method which was registered by the QPA plugin earlier. This method searches for “main” method symbol, creates another thread and runs the “main” method from within that thread. It must create another thread because calling “main” method blocks the caller until it exists and we must keep the Android UI thread free to allow the Android event loop to run.
In a later article, I will cover how to use JNI to do calls from/to Java to/from native (C/C++) world.
Finally, have a look at the current status of Qt on Android, what you’ll get in Qt 5.2 and what are the plans for Qt 5.3 for Android.
Qt Essentials status:
Module |
Qt 5.1 |
Qt 5.2 |
Qt 5.3 |
Qt Core |
missing system semaphores and shared memory |
shared memory is on my TODO list |
|
Qt Multimedia |
video and audio works, missing camera support |
brings camera support |
ATM no other plans |
Qt Network |
missing SSL support |
brings SSL support |
ATM no other plans |
|
|
|
|
Qt Quick Controls (erratum) |
missing android native style |
missing android native style |
on my TODO list |
Qt SQL |
only sqlite is provided by Qt-Project SDK |
||
Qt WebKit & Qt WebKitWidgets, Qt WebEngine |
missing |
There is hope for Qt WebEngine |
|
Qt Widgets |
missing android native style |
brings android native style |
ATM no other plans |
Qt GUI, QML, Quick,Quick Layouts, Test |
just works |
Qt Add-Ons status:
Module |
Qt 5.1 |
Qt 5.2 |
Qt 5.3 |
Qt Android Extras |
missing |
additional functionality for development on Android |
android services/binder support is on my TODO list |
Qt Bluetooth |
missing |
on my TODO list |
|
Qt NFC |
missing |
on my TODO list |
|
Qt Positioning |
missing |
on my TODO list |
|
Qt D-Bus |
missing, android uses the binder IPC. |
Missing, but as I said Qt will have something similar for Android |
|
Qt Sensors |
commonly used sensors |
more sensors added |
ATM no other plans |
Qt PrintSupport |
missing, no native print support on Android |
||
Qt OpenGL |
limited to one top level widget, can’t mix QGLWidget with other QWidget(s) |
there is hope to use one more top level widget can mix a single QGLWidget with other QWidgets |
|
Qt SerialPort |
missing |
support added |
ATM no other plans |
Qt Concurrent, Declarative, GraphicalEffects, ImageFormats, Script, ScriptTools, SVG, XML, XMLPatterns
|
just works |
Thank you for your time.
See you next time when we’ll discuss how to setup the development for Android.
Update: Qt on Android Episode 2 is available here