Integrate a Qt static library with running QCoreApplication into an android app over JNI
-
I need help for an integration project.
I developed a static library in Qt with async tasks or event loops like QCoreApplication and QNetworkAccessManager. In my static library I need a QCoreApplication instance and a QNetworkAccessManager instance. Principally the library includes signal-slots-mechanism.
In a past integration project I integrated this library into a native objC iOS app - this solution works fine.
Now, I will integrate this library into a native JAVA Android app over JNI - this step is very tricky for me.
First, I have an simple Qt class:
#ifndef TEST_H #define TEST_H #include <QObject> #include <QNetworkAccessManager> class Test : public QObject { public: explicit Test(QObject *parent = 0); void initManager(); private: QNetworkAccessManager *manager; }; #endif // TEST_H
This Test.class create a simple instance for QNetworkAccessManager and QCoreApplication:
#include "Test.h" #include <QDebug> #include <QCoreApplication> Test::Test(QObject *parent): QObject(parent) { } void Test::initManager() { qDebug() << "# initManager #"; this->onStarted(); // Direct function call; runs onStarted() in the main thread. - or not? // Create a manager instance qDebug() << "NEW QNetworkAccessManager instance ..."; manager = new QNetworkAccessManager(this); qDebug() << "QNetworkAccessManager instantiated ..."; QCoreApplication::exec(); } void Test::onStarted() { qDebug() << "# onStarted #"; if (QCoreApplication::instance() == NULL) { qDebug() << "NEW QCoreApplication instance ..."; int argc = 1; char * argv[] = {"webdav.app", NULL}; new QCoreApplication(argc, argv); qDebug() << "QCoreApplication instantiated ..."; } return; }
Now I call the method initManager() in my native android app over JNI:
static MYQLibrary webDAV; extern "C" { JNIEXPORT void JNICALL Java_com_dictateam_MYQLibrary_Interface_initManager(JNIEnv * env, jobject obj); }; JNIEXPORT void JNICALL Java_com_dictateam_MYQLibrary_Interface_initManager(JNIEnv * env, jobject obj) { webDAV.initManager(); return; }
In JAVA (native Android in MainActivity.onCreate()) I call the native method:
final Interface myInterface = new Interface(); System.out.println("Call initManager() from lib:"); Runnable r = new Runnable() { public void run() { try{ myInterface.initManager(); }catch(Exception e){ System.out.println(e.toString()); } } }; new Thread(r).start();
If i run this application on my smartphone, the app crashes with following log:
05-25 12:50:29.936: I/System.out(6341): Call debug() from lib: 05-25 12:50:29.936: D/(6341): ../MYQLibrary/MYQLibrary.cpp:93 (void MYQLibrary::debug() const): The MYQLibrary() says hello! 05-25 12:50:29.936: I/System.out(6341): Call initManager() from lib: 05-25 12:50:29.941: D/(6341): ../MYQLibrary/MYQLibrary.cpp:98 (void MYQLibrary::initManager()): # initManager # 05-25 12:50:29.941: W/(6341): (null):0 ((null)): QObject: Cannot create children for a parent that is in a different thread. 05-25 12:50:29.941: W/(6341): (Parent is MYQLibrary(0x60f83098), parent's thread is QThread(0x5cedfed0), current thread is QThread(0x5c8dac58) 05-25 12:50:29.941: D/(6341): ../MYQLibrary/test.cpp:14 (void Test::initManager()): # initManager # 05-25 12:50:29.941: D/(6341): ../MYQLibrary/test.cpp:75 (void Test::onStarted()): # onStarted # 05-25 12:50:29.941: D/(6341): ../MYQLibrary/test.cpp:83 (void Test::onStarted()): NEW QCoreApplication instance ... 05-25 12:50:29.941: W/(6341): (null):0 ((null)): WARNING: QApplication was not created in the main() thread. 05-25 12:50:29.941: D/webdav.app(6341): ../MYQLibrary/test.cpp:20 (void Test::initManager()): QCoreApplication::instance() is running ... 05-25 12:50:29.941: D/webdav.app(6341): ../MYQLibrary/test.cpp:23 (void Test::initManager()): NEW QNetworkAccessManager instance ... 05-25 12:50:29.941: A/libc(6341): Fatal signal 6 (SIGABRT) at 0x000018c5 (code=-6), thread 6366 (Thread-6412) 05-25 12:50:29.976: D/libEGL(6341): loaded /system/lib/egl/libEGL_mali.so 05-25 12:50:29.981: D/libEGL(6341): loaded /system/lib/egl/libGLESv1_CM_mali.so 05-25 12:50:29.981: D/libEGL(6341): loaded /system/lib/egl/libGLESv2_mali.so
How can I integrate my static library with a working event loop in the background (QCoreApplication and QNetworkAccessManager)?
This library includes several async tasks (Network communication by QNetworkAccessManager) by Signal-Slot-Mechanism. So I must have a working event loop by QCoreApplication.Please help me to find a solution for this case. Thank you in advanced! :-)