Trusted Software Excellence across Desktop and Embedded
Take a glance at the areas of expertise where KDAB excels ranging from swift troubleshooting, ongoing consulting and training to multi-year, large-scale software development projects.
Find out why customers from innovative industries rely on our extensive expertise, including Medical, Biotech, Science, Renewable Energy, Transportation, Mobility, Aviation, Automation, Electronics, Agriculture and Defense.
High-quality Embedded Engineering across the Stack
To successfully develop an embedded device that meets your expectations regarding quality, budget and time to market, all parts of the project need to fit perfectly together.
Learn more about KDAB's expertise in embedded software development.
Where the capabilities of modern mobile devices or web browsers fall short, KDAB engineers help you expertly architect and build high-functioning desktop and workstation applications.
Extensible, Safety-compliant Software for the Medical Sector
Create intelligent, patient-focused medical software and devices and stay ahead with technology that adapts to your needs.
KDAB offers you expertise in developing a broad spectrum of clinical and home-healthcare devices, including but not limited to, internal imaging systems, robotic surgery devices, ventilators and non-invasive monitoring systems.
Building digital dashboards and cockpits with fluid animations and gesture-controlled touchscreens is a big challenge.
In over two decades of developing intricate UI solutions for cars, trucks, tractors, scooters, ships, airplanes and more, the KDAB team has gained market leading expertise in this realm.
Build on Advanced Expertise when creating Modern UIs
KDAB assists you in the creation of user-friendly interfaces designed specifically for industrial process control, manufacturing, and fabrication.
Our specialties encompass the custom design and development of HMIs, enabling product accessibility from embedded systems, remote desktops, and mobile devices on the move.
Legacy software is a growing but often ignored problem across all industries. KDAB helps you elevate your aging code base to meet the dynamic needs of the future.
Whether you want to migrate from an old to a modern GUI toolkit, update to a more recent version, or modernize your code base, you can rely on over 25 years of modernization experience.
KDAB offers a wide range of services to address your software needs including consulting, development, workshops and training tailored to your requirements.
Our expertise spans cross-platform desktop, embedded and 3D application development, using the proven technologies for the job.
When working with KDAB, the first-ever Qt consultancy, you benefit from a deep understanding of Qt internals, that allows us to provide effective solutions, irrespective of the depth or scale of your Qt project.
Qt Services include developing applications, building runtimes, mixing native and web technologies, solving performance issues, and porting problems.
KDAB helps create commercial, scientific or industrial desktop applications from scratch, or update its code or framework to benefit from modern features.
Discover clean, efficient solutions that precisely meet your requirements.
Boost your team's programming skills with in-depth, constantly updated, hands-on training courses delivered by active software engineers who love to teach and share their knowledge.
Our courses cover Modern C++, Qt/QML, Rust, 3D programming, Debugging, Profiling and more.
The collective expertise of KDAB's engineering team is at your disposal to help you choose the software stack for your project or master domain-specific challenges.
Our particular focus is on software technologies you use for cross-platform applications or for embedded devices.
Since 1999, KDAB has been the largest independent Qt consultancy worldwide and today is a Qt Platinum partner. Our experts can help you with any aspect of software development with Qt and QML.
KDAB specializes in Modern C++ development, with a focus on desktop applications, GUI, embedded software, and operating systems.
Our experts are industry-recognized contributors and trainers, leveraging C++'s power and relevance across these domains to deliver high-quality software solutions.
KDAB can guide you incorporating Rust into your project, from as overlapping element to your existing C++ codebase to a complete replacement of your legacy code.
Unique Expertise for Desktop and Embedded Platforms
Whether you are using Linux, Windows, MacOS, Android, iOS or real-time OS, KDAB helps you create performance optimized applications on your preferred platform.
If you are planning to create projects with Slint, a lightweight alternative to standard GUI frameworks especially on low-end hardware, you can rely on the expertise of KDAB being one of the earliest adopters and official service partner of Slint.
KDAB has deep expertise in embedded systems, which coupled with Flutter proficiency, allows us to provide comprehensive support throughout the software development lifecycle.
Our engineers are constantly contributing to the Flutter ecosystem, for example by developing flutter-pi, one of the most used embedders.
KDAB invests significant time in exploring new software technologies to maintain its position as software authority. Benefit from this research and incorporate it eventually into your own project.
Start here to browse infos on the KDAB website(s) and take advantage of useful developer resources like blogs, publications and videos about Qt, C++, Rust, 3D technologies like OpenGL and Vulkan, the KDAB developer tools and more.
The KDAB Youtube channel has become a go-to source for developers looking for high-quality tutorial and information material around software development with Qt/QML, C++, Rust and other technologies.
Click to navigate the all KDAB videos directly on this website.
In over 25 years KDAB has served hundreds of customers from various industries, many of them having become long-term customers who value our unique expertise and dedication.
Learn more about KDAB as a company, understand why we are considered a trusted partner by many and explore project examples in which we have proven to be the right supplier.
The KDAB Group is a globally recognized provider for software consulting, development and training, specializing in embedded devices and complex cross-platform desktop applications.
Read more about the history, the values, the team and the founder of the company.
When working with KDAB you can expect quality software and the desired business outcomes thanks to decades of experience gathered in hundreds of projects of different sizes in various industries.
Have a look at selected examples where KDAB has helped customers to succeed with their projects.
KDAB is committed to developing high-quality and high-performance software, and helping other developers deliver to the same high standards.
We create software with pride to improve your engineering and your business, making your products more resilient and maintainable with better performance.
KDAB has been the first certified Qt consulting and software development company in the world, and continues to deliver quality processes that meet or exceed the highest expectations.
In KDAB we value practical software development experience and skills higher than academic degrees. We strive to ensure equal treatment of all our employees regardless of age, ethnicity, gender, sexual orientation, nationality.
Interested? Read more about working at KDAB and how to apply for a job in software engineering or business administration.
Update: Here you have also the Chinese version, thanks goes to Foruok.
In the last two Qt on Android episodes we learned how to use basic JNI on Android and how to use an external IDE to easily manage the Java part. In this episode, it is time to move forward and focus on extending our Qt on Android Java part and also how to interact with it using JNI in a "safe way".
In this part we are going to implement an SD-Card listener. This is quite a useful example for applications that are using SD-Cards to store their data, because if the application doesn't close all the opened files immediately when it gets the notification, it will be killed by the Android O.S.
As we've seen in Episode 5 it's quite easy to call a Java method from C/C++ and a C/C++ function from Java, but it doesn't work on all cases. But why not?
To understand why not, we need first to understand the Qt on Android architecture.
Architecture diagram:
A few words about the architecture diagram.
the left blue rectangle represents the Android UI thread
the right green rectangle represents the main Qt thread (where the main QEventLoop is running). Read Episode 1 if you want to learn more about Android UI & Qt threads)
the top (black) rectangle is the Java part of your application. As you can see the biggest part of it runs on the Android UI thread. The only case when the Java part runs on the Qt thread is when we call it from C/C++ from Qt thread (as most of the JNI calls will come from there).
the bottom (black) rectangle is the C/C++ (Qt) part of your application. As you can see the biggest part of it runs on the Qt thread. The only case when the C/C++ part runs on the Android UI thread is when it's called from the Java part from Android UI (as most of the Java callbacks will be from there).
Ok ... so what's the problem?
Well, the problem is that there are SOME Android APIs that MUST be called from Android UI thread, and when we call a Java method from C/C++ we do it from Qt thread. It means that we need a way to run that code on Android UI not on Qt thread. To do such a call, from C/C++ Qt thread to Java Android UI thread, we need to do 3 steps:
call a Java method from C/C++ Qt thread. The Java method will be executed in Qt thread, so we we need a way to access Android APIs in Android UI thread.
our Java method uses Activity.runOnUiThread to post a runnable on Android UI thread. This runnable will be executed by the Android event loop on Android UI thread.
the runnable accesses the Android APIs from Android UI thread.
The same problem occurs when Java calls a C/C++ function, because Java will call our C/C++ functions from Android UI and we need a way to pass that notification on Qt thread. Again there are 3 steps involved:
Qt event loop will execute that function on Qt thread.
Extending the Java part:
Before you start, make sure you read Episode 6 one more time because you'll need it to easily manage the Java files.
First step is to create a custom Activity by extending QtActivity and defining a method which will post our Runnable.
// src/com/kdab/training/MyActivity.javapackagecom.kdab.training;importorg.qtproject.qt5.android.bindings.QtActivity;publicclassMyActivityextendsQtActivity{// this method is called by C++ to register the BroadcastReceiver.publicvoidregisterBroadcastReceiver(){// Qt is running on a different thread than Android.// In order to register the receiver we need to execute it in the Android UI threadrunOnUiThread(newRegisterReceiverRunnable(this));}}
We need to do this to make sure that our custom Activity will be instantiated when the application starts.
Next step is to define our RegisterReceiverRunnable class:
The run method of this class will be called on Android UI thread. In run method we register our SDCardReceiver listener.
// src/com/kdab/training/RegisterReceiverRunnable.javapackagecom.kdab.training;importandroid.app.Activity;importandroid.content.Intent;importandroid.content.IntentFilter;publicclassRegisterReceiverRunnableimplementsRunnable{privateActivity m_activity;publicRegisterReceiverRunnable(Activity activity){ m_activity = activity;}// this method is called on Android Ui Thread@Overridepublicvoidrun(){IntentFilter filter =newIntentFilter(); filter.addAction(Intent.ACTION_MEDIA_MOUNTED); filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); filter.addDataScheme("file");// this method must be called on Android Ui Thread m_activity.registerReceiver(newSDCardReceiver(), filter);}}
Let's check what SDCardReceiver class looks like:
// src/com/kdab/training/SDCardReceiver.javapackagecom.kdab.training;importandroid.content.BroadcastReceiver;importandroid.content.Context;importandroid.content.Intent;publicclassSDCardReceiverextendsBroadcastReceiver{@OverridepublicvoidonReceive(Context context,Intent intent){// call the native method when it receives a new notificationif(intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED))NativeFunctions.onReceiveNativeMounted();elseif(intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED))NativeFunctions.onReceiveNativeUnmounted();}}
SDCardReceiver overrides onReceive method, then it uses the declared native functions to send the notification to C/C++.
Last step is to declare our native functions that we used in SDCardReceiver:
// src/com/kdab/training/NativeFunctions.javapackagecom.kdab.training;publicclassNativeFunctions{// define the native function// these functions are called by the BroadcastReceiver object// when it receives a new notificationpublicstaticnativevoidonReceiveNativeMounted();publicstaticnativevoidonReceiveNativeUnmounted();}
Architecture diagram Java:
Let's see the summary of the Java part calls on our architecture diagram:
Extending C/C++ part:
Now let's see how we extend the C/C++ part. To illustrate how to do it, I'm using a simple widget application.
First thing we need to do, is to call the registerBroadcastReceiver method.
// main.cpp#include"mainwindow.h"#include<QApplication>#include<QtAndroid>intmain(int argc,char*argv[]){ QApplication a(argc, argv);// call registerBroadcastReceiver to register the broadcast receiverQtAndroid::androidActivity().callMethod<void>("registerBroadcastReceiver","()V");MainWindow::instance().show();return a.exec();}
// native.cpp#include<jni.h>#include<QMetaObject>#include"mainwindow.h"// define our native static functions// these are the functions that Java part will call directly from Android UI threadstaticvoidonReceiveNativeMounted(JNIEnv */*env*/, jobject /*obj*/){// call MainWindow::onReceiveMounted from Qt threadQMetaObject::invokeMethod(&MainWindow::instance(),"onReceiveMounted", Qt::QueuedConnection);}staticvoidonReceiveNativeUnmounted(JNIEnv */*env*/, jobject /*obj*/){// call MainWindow::onReceiveUnmounted from Qt thread, we wait until the called function finishes// in this function the application should close all its opened files, otherwise it will be killedQMetaObject::invokeMethod(&MainWindow::instance(),"onReceiveUnmounted", Qt::BlockingQueuedConnection);}//create a vector with all our JNINativeMethod(s)static JNINativeMethod methods[]={{"onReceiveNativeMounted","()V",(void*)onReceiveNativeMounted},{"onReceiveNativeUnmounted","()V",(void*)onReceiveNativeUnmounted},};// this method is called automatically by Java after the .so file is loadedJNIEXPORT jint JNI_OnLoad(JavaVM* vm,void*/*reserved*/){ JNIEnv* env;// get the JNIEnv pointer.if(vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)!= JNI_OK)return JNI_ERR;// search for Java class which declares the native methods jclass javaClass = env->FindClass("com/kdab/training/NativeFunctions");if(!javaClass)return JNI_ERR;// register our native methodsif(env->RegisterNatives(javaClass, methods,sizeof(methods)/sizeof(methods[0]))<0){return JNI_ERR;}return JNI_VERSION_1_6;}
In native.cpp we are registering the native functions. From our static native functions we are using QMetaObject::invokeMethod to post the slots call to Qt thread.
MainWindow class is used just to add some text to our plainText control when it gets a notification. Calling these functions from Android thread might be very harmful to our application health - it might lead to crashes or unexpected behavior, so they MUST be called from Qt thread.
Architecture diagram C/C++:
This is the summary of C/C++ calls on our architecture diagram:
Architecture diagram Java & C/C++:
This is the summary of all the calls that we've done in C/C++ and in Java.
This example is very good, but still the show stopper for me is the possibility to handle intents. Maybe you have some working example for that? I've described in one of the emails on interest mailing list what I've achieved so far, but haven't got it working:
http://lists.qt-project.org/pipermail/interest/2015-April/016320.html
And of course, please join this and other Qt+Android conversations on the lists!
3 - Jun - 2015
BogDan Vatra
disclaimer: I read your mail very briefly.
So, you want to create an application (viewer) that handles some file extensions? I'm pretty sure it is already possible, you just need to tweak a little bit your android manifest file, set APPLICATION_PARAMETERS [0] correctly in your custom activity, make sure your let the application to quit and that it. If you'll control the intent then you can pass the params via applicationArguments stringExtras key [1].
Invoking it for the first time is not a problem, only minor QtActivity code modification is needed. But then when you switch to file manager and try to open another file - android will not quit the first instance of viewer, it will just restore it, with the first opened file. I was not able to open second file when the first one is already opened.
3 - Jun - 2015
BogDan Vatra
First and foremost, as I said many times, you should NOT change QtActivity, instead you should extend it.
If you want to make sure that your application quits you can listen for QGuiApplication::applicationStateChanged [0] and quit the application when state is Qt::ApplicationSuspended.
Sorry, I meant QtNative, not QtActivity. I would contribute the fix upstream if I will be able to make it work as I wanted.
I see your point about quitting, but it will affect the startup time on every new intent.
3 - Jun - 2015
BogDan Vatra
If your fix doesn't break anything else than you can upstream it.
If you want to keep your application running than you need to send the params using JNI.
18 - Jun - 2015
Federico
I've solved this problem in another way. Instead of restarting the application I have set the activity with property android:launchMode="singleTask"; this way the same, opened, instance is called when an intent is launched. I've also extended the QtActivity with the method "onNewIntent(Intent i)" in which I call "setIntent(i): this way the subsequent call to the extras() method will return the parameters contained in the new Intent, instead of the original intent which started the app. I've only ONE last issue: notify Qt of the new Intent. Guess this episode is what I'm looking for. Thanks BogDan! :)
Hi, BogDan Vatra. In my practice, I tend to register natives by using my custom functions and let it run before QQmlApplicationEngine gets started rather than "JNI_OnLoad( )" function, and it also works.
In fact I'm going to encapsulate some open authentication platforms into my plugin and expose some informations to QML environments, registering methods within "QQmlExtensionPlugin::registerTypes( )" function seems a good practice.
3 - Jun - 2015
BogDan Vatra
It doesn't matter where you register them as long as you'll register them before the java part calls them.
JNI_OnLoad( ) gives us everything we need to register them (JavaVM pointer), that's why I'm using it and that is the reason why I'm telling people to use it.
14 - Jun - 2015
jiangcaiyang
How is using AsyncTask on Java side in replace of Runnable?
16 - Jun - 2015
BogDan Vatra
HUH ?!?! The idea is to run some code on Android UI thread.
AsyncTask is used for something else. It's usefull when you want to do some heavy work in background and publish the results on Android UI thread. I don't see how AsyncTask is better than the humble Runnable and Activity.runOnUiThread for what we need...
Of course AsyncTask might be useful for other examples, but for the example in the article is useless.
16 - Jun - 2015
jiangcaiyang
What about the solution on creating instance in C++ by JNI whereas it affiances to Android UI thread. subclass Activity and write a new clause is a solution, but I don't want to disturb QtActivity.
16 - Jun - 2015
BogDan Vatra
I think I fail to follow you :) .
You want to create a new Activity from JNI? If the activity is not declared in your manifest file, you can't create a new one at runtime.
Also the main Activity and Qt needs separate threads because they have their own event loops and they can't leave togheter into a single thread (check http://www.kdab.com/qt-on-android-episode-1 for more info on this matter).
15 - Jul - 2015
daniel
Hello ,I have a "already working " Qt application ,an instant messaging one ,it uses QXmpp and I am porting it to android.
The problem I am facing is that when the application is inactive for some time it is killed by the system .I tried to remedy on this by writting an android service using (asmack) and handling received messages and opening my application again and pass in the received messages .
This is starting to look like a bad design as I have to log off from the server and let the service take control every time the user minimises the app or when the screen goes black.
I was wondering if there is a better way of hanling "long running operations on android (Qt) or should I just offload the Instant messaging details to the background service.
Thank you.
23 - Oct - 2015
BogDan Vatra
Using a service is the Android way to do long term background operations.
So, IMHO you should create a service which processes the data, post notifications and start the Qt UI using an Intent if needed.
23 - Oct - 2015
Tilly Pavone
Hello Bodgan, thank you for your job (yes, I'm really impressed!).
I have a question on how the Android UI thread and the Qt thread relate to the process running the Android app, in particular when it comes to acquire a WakeLock.
While developing a GPS app, I ended up writing an example that shows how, if holding a PARTIAL_WAKE_LOCK, the QtActivity keeps working also in the background, as expected, while the Qt thread goes to sleep.
How is that possible? Do Android WakeLocks, as it seems, get effect at a thread level?
Here is an excerpt from my sample:
*** java ***
public class UtyActivity extends QtActivity
{
private PowerManager.WakeLock m_wakelock;
Timer m_timer;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// starts Android UI task
m_timer = new Timer();
DebugTask task = new DebugTask();
m_timer.schedule(task, 1, 10000);
// acquire a partial WakeLock here (not working using JNI from Qt)
// NB: We are in the Android UI thread here, aren't we?
// (anyway I also tryed using runOnUiThread)
Context context = getApplicationContext();
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
m_wakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "com.utillyty.android.wakelock");
m_wakelock.acquire();
}
// ---> THIS KEEPS WORKING ALSO IN BACKGROUND
class DebugTask extends TimerTask
{
public void run()
{
// http get on test server: the request is always delivered
...
========== C++ ==========
// ---> THIS BLOCKS WHILE APP IN THE BACKGROUND
void MainPanel::timerEvent(QTimerEvent *)
{
// same http get as java: no request is delivered while in the background
...
23 - Oct - 2015
BogDan Vatra
By default the main QEventLoop is freezed when it goes in background. We need to do it because the surface that Qt needs to paint to is not available anymore and if you try to paint something your application might crash.
There are two ways to keep going on Qt world after it goes in background:
- create a new thread , call QThread::exec() then create all the timers and other QObjects that you need the in that thread.
- don't freeze the Qt main loop. You need to edit AndroidManifest.xml and set "android.app.background_running" to "true", but you must make sure you don't draw anything when the application is backgrounded.
23 - Oct - 2015
Tilly Pavone
It works great!
If I need to draw anything when the app may be running in the background, I just check if "isVisible()" is "false" and if so, store the data in memory and do the job in the "showEvent()" function.
Thanks a lot!
26 - Oct - 2016
Sudha
Hello, I need to control device orientation, both iOS and Android from qt5.6 and c++. What's the best way
12 - Nov - 2016
seniorivn
Hi, it is the best articles about qt on android that i've found. But it's didn't answer on my questions :(
Here is my problem:
1) i'm trying to write soft keyboard using qt.
2) android use android.view.View to draw keyboard
3) so i need to use View to draw qt interface, but standard way to draw qt on android is QtActivity.
4) I've found a way to do that, by extendinng View, with custom onDraw() that will get bitmap of qt interface by grabWindow() and put it into view.
5) Do you think it's normal solution? Does anyone have any better ideas?
Thanks anyway, you did a great job.
14 - Nov - 2016
BogDan Vatra
I think you're wrong, "standard" way to draw qt is by using a [Qt]SurfaceView not the QtActivity.
QtActivity is used just to forward all the events to Qt world.
I never tried to write an android keyboard so, I don't know all the details, but using grabWindow() doesn't seem the best solution...
If you can add a single SurfaceView to android.view.View that (apparently) is needed to draw the keyboard, then Qt can use it to draw its stuff too.
2 - Dec - 2016
Valentin OFFNER
Hi,
I have a little question about this article and signals.
Shoud I always use the QMetaObject::InvokeMethod or can I call the Q_EMIT directly?
thanks very much to sharing your knowledge about Qt/Android with us.
I have read your Android/Qt article and watched some of your presentation at Qt Con.
I have developed a quit simple Qt/Android application, which is using the Camera and some other features of my Smartphone.
The application is working well when I use "Bundle Qt libraries in APK" but when I try "Use Ministro service to install Qt". Nothing works!
My Application uses some JNI functions, so I have create JNI_OnLoad() function as your show in your presentation at Qt Con 2016. But when I start it I've got following error:
E/art ( 8451): No implementation found for void com.geocept.android.NativeFunctions.onWifiStateChanged(boolean) (tried Java_com_geocept_android_NativeFunctions_onWifiStateChanged and Java_com_geocept_android_NativeFunctions_onWifiStateChanged__Z)
This only happens when I generate the APK with "Use Ministro service to install Qt".
Why?
Can you help me?
19 - Dec - 2016
BogDan Vatra
I'll need more info on this matter: e.g. what Qt version are you using?
19 - Dec - 2016
Fabrice Mousset
Here my configuration:
- Qt 5.7.1 / Android armeabi-v7
- Android NDK r13b
- Qt Creator v4.2.0
- Workstation: Windows 7 pro/64 bit
- Android Lollipop
- Android API level used: 21
19 - Dec - 2016
BogDan Vatra
Qt 5.7.x wasn't yet uploaded to Ministro repos, I'm still testing it ...
I hope I'll upload it in a few days.
19 - Dec - 2016
Fabrice Mousset
Thanks for your answer,
Do you have a deadline for this update?
Before end of this week (before Xmas) or next year?
I have to inform customer about software availability.
20 - Dec - 2016
Fabrice Mousset
Hi BogDan,
in the meantime, I found a quick&dirty solution which "WorksForMe(tm)".
To save data space on APK transfer to the device, I have create a full APK.
On this APK I have extract all Qt specific stuff.
Those files are transferred into device internal storage (backup copy).
For every next APK release, I remove Qt stuff from APK.
Send this small APK (less than 2 MB) to the device, on device side a insert remove Qt stuff to complete the APK then start a "normal" APK install on Android.
It is very dirty but it works for my needs.
Perhaps, you can provide an "extended" version of Ministro, with a kind of "Off-Line" or "Static" mode in which it is possible to setup a device with specified Qt version, for example downloaded from Qt repository. The transfer this version on device.
So all APK generated for this device do not need any Qt dll/qml/whatever. This can be useful for a business solution.
I don't think this will be so much changes on Ministro side.
What do you think about this?
Regards
Fabrice
20 - Dec - 2016
BogDan Vatra
I just uploaded Qt 5.7 a few hours ago, it should already be visible.
18 - Dec - 2016
Ahmed Arif
just wandering isn't possible to make the "static void onReceiveNativeMounted" inside Mainwindow's class so it will be "static void Mainwindow::onReceiveNativeMounted" and then call ui->plainTextEdit.... directly from it ? this could be more elegant i guess ?...
imagine if we have many many functions to pass with it data from java to C++, making statics functions along side with the same number of slots will rise the ability of maintaining the code ...
19 - Dec - 2016
BogDan Vatra
Calling a static method (from your class) or a static function it doesn't change the thread from it's called.
So "Mainwindow::onReceiveNativeMounted" is called from Android UI thread no matter what and trying to call "ui->plainTextEdit" directly (though you can't use it directly because "ui" is not accessible from a static method) will not automatically switch the threads and it will lead to a crash (sooner or later).
20 - Oct - 2020
Wenderson Costa
Good explanation, but you would a actualization of this.
19 - Jan - 2021
BogDan Vatra
+90% of this material should still apply today.
I don't know when I'll have time to update it.
Bogdan Vatra
Senior Software Engineer
Bogdan Vatra is a Senior Software Engineer at KDAB
36 Comments
2 - Jun - 2015
Stanislav
Bogdan,
This example is very good, but still the show stopper for me is the possibility to handle intents. Maybe you have some working example for that? I've described in one of the emails on interest mailing list what I've achieved so far, but haven't got it working: http://lists.qt-project.org/pipermail/interest/2015-April/016320.html
And of course, please join this and other Qt+Android conversations on the lists!
3 - Jun - 2015
BogDan Vatra
disclaimer: I read your mail very briefly.
So, you want to create an application (viewer) that handles some file extensions? I'm pretty sure it is already possible, you just need to tweak a little bit your android manifest file, set APPLICATION_PARAMETERS [0] correctly in your custom activity, make sure your let the application to quit and that it. If you'll control the intent then you can pass the params via applicationArguments stringExtras key [1].
[0] http://code.qt.io/cgit/qt/qtbase.git/tree/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java#n137 [1] http://code.qt.io/cgit/qt/qtbase.git/tree/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java#n652
3 - Jun - 2015
Stanislav
Invoking it for the first time is not a problem, only minor QtActivity code modification is needed. But then when you switch to file manager and try to open another file - android will not quit the first instance of viewer, it will just restore it, with the first opened file. I was not able to open second file when the first one is already opened.
3 - Jun - 2015
BogDan Vatra
First and foremost, as I said many times, you should NOT change QtActivity, instead you should extend it.
If you want to make sure that your application quits you can listen for QGuiApplication::applicationStateChanged [0] and quit the application when state is Qt::ApplicationSuspended.
[0] https://doc-snapshots.qt.io/qt5-5.4/qguiapplication.html#applicationStateChanged
3 - Jun - 2015
Stanislav
Sorry, I meant QtNative, not QtActivity. I would contribute the fix upstream if I will be able to make it work as I wanted.
I see your point about quitting, but it will affect the startup time on every new intent.
3 - Jun - 2015
BogDan Vatra
If your fix doesn't break anything else than you can upstream it.
If you want to keep your application running than you need to send the params using JNI.
18 - Jun - 2015
Federico
I've solved this problem in another way. Instead of restarting the application I have set the activity with property android:launchMode="singleTask"; this way the same, opened, instance is called when an intent is launched. I've also extended the QtActivity with the method "onNewIntent(Intent i)" in which I call "setIntent(i): this way the subsequent call to the extras() method will return the parameters contained in the new Intent, instead of the original intent which started the app. I've only ONE last issue: notify Qt of the new Intent. Guess this episode is what I'm looking for. Thanks BogDan! :)
3 - Jun - 2015
foruok
Hi,BogDan,here is the Chinese version:http://blog.csdn.net/foruok/article/details/46323129
3 - Jun - 2015
BogDan Vatra
Thanks.
3 - Jun - 2015
jiangcaiyang
Hi, BogDan Vatra. In my practice, I tend to register natives by using my custom functions and let it run before QQmlApplicationEngine gets started rather than "JNI_OnLoad( )" function, and it also works. In fact I'm going to encapsulate some open authentication platforms into my plugin and expose some informations to QML environments, registering methods within "QQmlExtensionPlugin::registerTypes( )" function seems a good practice.
3 - Jun - 2015
BogDan Vatra
It doesn't matter where you register them as long as you'll register them before the java part calls them.
JNI_OnLoad( ) gives us everything we need to register them (JavaVM pointer), that's why I'm using it and that is the reason why I'm telling people to use it.
14 - Jun - 2015
jiangcaiyang
How is using AsyncTask on Java side in replace of Runnable?
16 - Jun - 2015
BogDan Vatra
HUH ?!?! The idea is to run some code on Android UI thread. AsyncTask is used for something else. It's usefull when you want to do some heavy work in background and publish the results on Android UI thread. I don't see how AsyncTask is better than the humble Runnable and Activity.runOnUiThread for what we need... Of course AsyncTask might be useful for other examples, but for the example in the article is useless.
16 - Jun - 2015
jiangcaiyang
What about the solution on creating instance in C++ by JNI whereas it affiances to Android UI thread. subclass Activity and write a new clause is a solution, but I don't want to disturb QtActivity.
16 - Jun - 2015
BogDan Vatra
I think I fail to follow you :) .
You want to create a new Activity from JNI? If the activity is not declared in your manifest file, you can't create a new one at runtime.
Also the main Activity and Qt needs separate threads because they have their own event loops and they can't leave togheter into a single thread (check http://www.kdab.com/qt-on-android-episode-1 for more info on this matter).
15 - Jul - 2015
daniel
Hello ,I have a "already working " Qt application ,an instant messaging one ,it uses QXmpp and I am porting it to android.
The problem I am facing is that when the application is inactive for some time it is killed by the system .I tried to remedy on this by writting an android service using (asmack) and handling received messages and opening my application again and pass in the received messages .
This is starting to look like a bad design as I have to log off from the server and let the service take control every time the user minimises the app or when the screen goes black.
I was wondering if there is a better way of hanling "long running operations on android (Qt) or should I just offload the Instant messaging details to the background service.
Thank you.
23 - Oct - 2015
BogDan Vatra
Using a service is the Android way to do long term background operations. So, IMHO you should create a service which processes the data, post notifications and start the Qt UI using an Intent if needed.
23 - Oct - 2015
Tilly Pavone
Hello Bodgan, thank you for your job (yes, I'm really impressed!).
I have a question on how the Android UI thread and the Qt thread relate to the process running the Android app, in particular when it comes to acquire a WakeLock.
While developing a GPS app, I ended up writing an example that shows how, if holding a PARTIAL_WAKE_LOCK, the QtActivity keeps working also in the background, as expected, while the Qt thread goes to sleep.
How is that possible? Do Android WakeLocks, as it seems, get effect at a thread level?
Here is an excerpt from my sample:
*** java ***
public class UtyActivity extends QtActivity { private PowerManager.WakeLock m_wakelock; Timer m_timer;
========== C++ ==========
// ---> THIS BLOCKS WHILE APP IN THE BACKGROUND void MainPanel::timerEvent(QTimerEvent *) { // same http get as java: no request is delivered while in the background
23 - Oct - 2015
BogDan Vatra
By default the main QEventLoop is freezed when it goes in background. We need to do it because the surface that Qt needs to paint to is not available anymore and if you try to paint something your application might crash.
There are two ways to keep going on Qt world after it goes in background: - create a new thread , call QThread::exec() then create all the timers and other QObjects that you need the in that thread. - don't freeze the Qt main loop. You need to edit AndroidManifest.xml and set "android.app.background_running" to "true", but you must make sure you don't draw anything when the application is backgrounded.
23 - Oct - 2015
Tilly Pavone
It works great! If I need to draw anything when the app may be running in the background, I just check if "isVisible()" is "false" and if so, store the data in memory and do the job in the "showEvent()" function. Thanks a lot!
26 - Oct - 2016
Sudha
Hello, I need to control device orientation, both iOS and Android from qt5.6 and c++. What's the best way
12 - Nov - 2016
seniorivn
Hi, it is the best articles about qt on android that i've found. But it's didn't answer on my questions :( Here is my problem: 1) i'm trying to write soft keyboard using qt. 2) android use android.view.View to draw keyboard 3) so i need to use View to draw qt interface, but standard way to draw qt on android is QtActivity. 4) I've found a way to do that, by extendinng View, with custom onDraw() that will get bitmap of qt interface by grabWindow() and put it into view.
5) Do you think it's normal solution? Does anyone have any better ideas?
Thanks anyway, you did a great job.
14 - Nov - 2016
BogDan Vatra
I think you're wrong, "standard" way to draw qt is by using a [Qt]SurfaceView not the QtActivity. QtActivity is used just to forward all the events to Qt world. I never tried to write an android keyboard so, I don't know all the details, but using grabWindow() doesn't seem the best solution... If you can add a single SurfaceView to android.view.View that (apparently) is needed to draw the keyboard, then Qt can use it to draw its stuff too.
2 - Dec - 2016
Valentin OFFNER
Hi,
I have a little question about this article and signals. Shoud I always use the QMetaObject::InvokeMethod or can I call the Q_EMIT directly?
OR
19 - Dec - 2016
BogDan Vatra
I don't think Q_EMIT (which is the same thing as emit) will delegate the call to callee thread.
static void notifyXXXX(JNIEnv env, jobject, jlong id) { JData const mp = mDataObjects[id]; jData*const mp = mDataObjects[id]; if (mp) QMetaObject::invokeMethod(mp, “callTheSignalMethodDirectly”); }
16 - Dec - 2016
Fabrice Mousset
Hi BogDan,
thanks very much to sharing your knowledge about Qt/Android with us. I have read your Android/Qt article and watched some of your presentation at Qt Con. I have developed a quit simple Qt/Android application, which is using the Camera and some other features of my Smartphone. The application is working well when I use "Bundle Qt libraries in APK" but when I try "Use Ministro service to install Qt". Nothing works!
My Application uses some JNI functions, so I have create JNI_OnLoad() function as your show in your presentation at Qt Con 2016. But when I start it I've got following error:
This only happens when I generate the APK with "Use Ministro service to install Qt". Why?
Can you help me?
19 - Dec - 2016
BogDan Vatra
I'll need more info on this matter: e.g. what Qt version are you using?
19 - Dec - 2016
Fabrice Mousset
Here my configuration: - Qt 5.7.1 / Android armeabi-v7 - Android NDK r13b - Qt Creator v4.2.0 - Workstation: Windows 7 pro/64 bit - Android Lollipop - Android API level used: 21
19 - Dec - 2016
BogDan Vatra
Qt 5.7.x wasn't yet uploaded to Ministro repos, I'm still testing it ... I hope I'll upload it in a few days.
19 - Dec - 2016
Fabrice Mousset
Thanks for your answer, Do you have a deadline for this update? Before end of this week (before Xmas) or next year?
I have to inform customer about software availability.
20 - Dec - 2016
Fabrice Mousset
Hi BogDan,
in the meantime, I found a quick&dirty solution which "WorksForMe(tm)". To save data space on APK transfer to the device, I have create a full APK. On this APK I have extract all Qt specific stuff. Those files are transferred into device internal storage (backup copy). For every next APK release, I remove Qt stuff from APK. Send this small APK (less than 2 MB) to the device, on device side a insert remove Qt stuff to complete the APK then start a "normal" APK install on Android.
It is very dirty but it works for my needs.
Perhaps, you can provide an "extended" version of Ministro, with a kind of "Off-Line" or "Static" mode in which it is possible to setup a device with specified Qt version, for example downloaded from Qt repository. The transfer this version on device. So all APK generated for this device do not need any Qt dll/qml/whatever. This can be useful for a business solution. I don't think this will be so much changes on Ministro side. What do you think about this?
Regards
Fabrice
20 - Dec - 2016
BogDan Vatra
I just uploaded Qt 5.7 a few hours ago, it should already be visible.
18 - Dec - 2016
Ahmed Arif
just wandering isn't possible to make the "static void onReceiveNativeMounted" inside Mainwindow's class so it will be "static void Mainwindow::onReceiveNativeMounted" and then call ui->plainTextEdit.... directly from it ? this could be more elegant i guess ?... imagine if we have many many functions to pass with it data from java to C++, making statics functions along side with the same number of slots will rise the ability of maintaining the code ...
19 - Dec - 2016
BogDan Vatra
Calling a static method (from your class) or a static function it doesn't change the thread from it's called. So "Mainwindow::onReceiveNativeMounted" is called from Android UI thread no matter what and trying to call "ui->plainTextEdit" directly (though you can't use it directly because "ui" is not accessible from a static method) will not automatically switch the threads and it will lead to a crash (sooner or later).
20 - Oct - 2020
Wenderson Costa
Good explanation, but you would a actualization of this.
19 - Jan - 2021
BogDan Vatra
+90% of this material should still apply today. I don't know when I'll have time to update it.