[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