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! :-)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.