[Android-development] Integrate a Qt static library with running QCoreApplication into an android app over JNI
Maik Ziemert
mail at moozoom.de
Mon May 30 12:39:10 CEST 2016
Hello developers,
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! :-)
Best greetings,
Maik
More information about the Android-development
mailing list