2

In the qt main thread I successfully can run this:

 jbyteArray jBuffer = _env->NewByteArray(bufferSize);

The _env is a QAndroidJniEnvironment. but If I try to use _env in the run function of a QRunnable, the application crashes and this error occurs:

Fatal signal 11 (SIGSEGV), code 1

This is the code:

class HelloWorldTask : public QRunnable
{
    QAndroidJniEnvironment * _env;
    void run()
    {
        qDebug() << "Hello world from thread" << QThread::currentThread();

        jbyteArray jBuffer = (*_env)->NewByteArray(10);
        qDebug() << "Hello 2 world from thread" << QThread::currentThread();
    }
public:
    void setPointer(QAndroidJniEnvironment * p){
        _env = p;
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();


    HelloWorldTask * hello = new HelloWorldTask();
    QAndroidJniEnvironment env;
    QAndroidJniEnvironment * p = & env;
    hello->setPointer(p);
    QThreadPool::globalInstance()->start(hello);
    return a.exec();
}

Could you please tell me how can I use the pointer to the QAndroidJniEnvironment or QAndroidJniObject in a new Qthread? so the application ui remains responsive during the execution of java process.

a.toraby
  • 3,232
  • 5
  • 41
  • 73

1 Answers1

2

Only 15 people have read this question so far. And still no answer. My be it's a very hard or very easy question to answer!! Anyway I found the solution with the help of qt forum users. Here is the working code:

class HelloWorldTask : public QRunnable
{
    QAndroidJniEnvironment * _env;
    void run()
    {
        JNIEnv * jniEnv;
        JavaVM * jvm = _env->javaVM();
        qDebug() << "Getting jni environment";
        jvm->GetEnv(reinterpret_cast<void**>(&_env), JNI_VERSION_1_6);
        qDebug() << "Attaching current thread";
        jvm->AttachCurrentThread(&jniEnv,NULL);
        qDebug() << "Creating byte array" ;
        jbyteArray jBuffer = jniEnv->NewByteArray(10);
        qDebug() << "byte array created" ;
        jvm->DetachCurrentThread();
    }
public:
    void setPointer(QAndroidJniEnvironment * p){
        _env = p;
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();


    HelloWorldTask * hello = new HelloWorldTask();


    QAndroidJniEnvironment * env;
    hello->setPointer(env);
    // QThreadPool takes ownership and deletes 'hello' automatically
    QThreadPool::globalInstance()->start(hello);
    return a.exec();
}

You should call AttachCurrentThread to use a jni environment pointer in another thread. I hope this helps someone.

a.toraby
  • 3,232
  • 5
  • 41
  • 73
  • a QAndroidJniEnvironment attaches the thread it's create on (if needed), so you shouldn't move it between threads. If you need to attach another thread just create a new QAndroidJniEnvironment instance on that thread. – cstream Apr 27 '15 at 23:42
  • QAndroidJniEnvironment * env; non initialized pointer used here : _env->javaVM(); This code really runs ? – SR_ Mar 17 '18 at 22:53