QT to Android serial port API problem

1,195 views
Skip to first unread message

Asmas Samas

unread,
Jan 6, 2012, 8:17:07 AM1/6/12
to android-qt
Hello,


I am trying to access to Android (Galaxy TAB 10.1) RS232 using
necessitas QT:
Please read post in QT Centre:
http://www.qtcentre.org/threads/46525-QT-to-Android-serial-port-API-problem?highlight=android


I tried to make simple program using example:
http://jgoday.wordpress.com/2009/04/...with-qt-part1/
to make sure that program is able to run using JNI.


At the moment I am able to compile project and Get simple program run
on
Desktop by returning JAVA version

But, compiling project for Android error appears:
/home/darka/ProgramFiles/QT_work/Android/JNI_1/test_JNI-build--
Necessitas_Qt_4_8_0_for_Android_armv7a_Release/../../../../necessitas/
Android/Qt/480/armeabi-v7a/src/android/cpp/qtmain_android.cpp:62:
error: invalid conversion from 'JNIEnv**' to 'void**'

An error points to file qtmain_android.cpp:62:

JNIEnv* env;
points here-> if (m_javaVM->AttachCurrentThread(&env, NULL)<0)
{
qCritical()<<"AttachCurrentThread failed";
return false;
}

Below is listed main.cpp with code:



#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <jni.h>
//#include </home/darka/ProgramFiles/necessitas/android-ndk-r6b/
platforms/android-9/arch-arm/usr/include/jni.h>
//#include </home/darka/ProgramFiles/necessitas/android-ndk-r6b/
platforms/android-9/arch-arm/usr/include/pthread.h>



JavaVM *gJavaVM;
static jobject gInterfaceObject;

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}

MainWindow::~MainWindow()
{
delete ui;
}

const char *getPropertyValue(JNIEnv *env, const char *name)
{
// Calling System.getProperty(propertyName);
jclass systemClass = env->FindClass("java/lang/System");
jmethodID getPropertyMethod = env->GetStaticMethodID(systemClass,
"getProperty",
"(Ljava/lang/
String;)Ljava/lang/String;");
jstring propertyName = env->NewStringUTF(name);
jstring value = (jstring) env->CallStaticObjectMethod(systemClass,

getPropertyMethod,

propertyName);

return env->GetStringUTFChars(value, NULL);
}


void MainWindow::on_pushButton_clicked()
{

// callback_handler((char *) "Called from native thread");
JavaVM *vm;
JNIEnv *env;
JavaVMInitArgs args;
jint ret;

args.version = JNI_VERSION_1_2;
args.nOptions = 0;
args.ignoreUnrecognized = JNI_FALSE;

ret = JNI_CreateJavaVM(&vm, (void **) &env, &args);
ui->textEdit->append(QString(getPropertyValue(env, "java.version")));
ui->textEdit->append( QString(getPropertyValue(env, "java.vendor")));

vm->DestroyJavaVM();

}



*.pro file contains:

QT += core gui

TARGET = test_JNI
TEMPLATE = app


SOURCES += main.cpp\
mainwindow.cpp

HEADERS += mainwindow.h

FORMS += mainwindow.ui


JAVA_HOME = /usr/lib/jvm/java-1.6.0-openjdk
INCLUDEPATH += $$JAVA_HOME/include
INCLUDEPATH += $$JAVA_HOME/include/linux

CONFIG += mobility
MOBILITY =

symbian {
TARGET.UID3 = 0xe014d50f
# TARGET.CAPABILITY +=
TARGET.EPOCSTACKSIZE = 0x14000
TARGET.EPOCHEAPSIZE = 0x020000 0x800000
}

OTHER_FILES += \
android/res/values-zh-rCN/strings.xml \
android/res/values-nb/strings.xml \
android/res/values-ms/strings.xml \
android/res/values-it/strings.xml \
android/res/values-nl/strings.xml \
android/res/values-id/strings.xml \
android/res/values-el/strings.xml \
android/res/drawable/logo.png \
android/res/drawable/icon.png \
android/res/drawable-mdpi/icon.png \
android/res/values-zh-rTW/strings.xml \
android/res/values-pt-rBR/strings.xml \
android/res/values/strings.xml \
android/res/values/libs.xml \
android/res/values-rs/strings.xml \
android/res/drawable-ldpi/icon.png \
android/res/values-fa/strings.xml \
android/res/drawable-hdpi/icon.png \
android/res/values-de/strings.xml \
android/res/values-fr/strings.xml \
android/res/values-ro/strings.xml \
android/res/values-ja/strings.xml \
android/res/layout/splash.xml \
android/res/values-es/strings.xml \
android/res/values-ru/strings.xml \
android/res/values-pl/strings.xml \
android/res/values-et/strings.xml \
android/src/org/kde/necessitas/ministro/IMinistro.aidl \
android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl \
android/src/org/kde/necessitas/origo/QtApplication.java \
android/src/org/kde/necessitas/origo/QtActivity.java \
android/AndroidManifest.xml




So.. any help?? What am I doing wrong??

Best regards,
AS

Tyler Mandry

unread,
Jan 7, 2012, 9:59:54 PM1/7/12
to andro...@googlegroups.com
What platform are you compiling on? What version of the NDK and compiler are you using?
--
Tyler Mandry

ASM

unread,
Jan 9, 2012, 7:34:49 AM1/9/12
to andro...@googlegroups.com

Hello,

I am using Ubuntu 11.10, and android-ndk-r7.

Actually I found some nice work related to serial communication:

http://v-lad.org/projects/gnu.io.android/#binariesDL


But any way I have JNI running on QT problem. As I understood without it I will be unable to compile any code.

Is there any simple example for Necessitas QT how to call java functions (JNI) ???

Best regards,
AS

mingw android

unread,
Jan 9, 2012, 9:07:40 AM1/9/12
to andro...@googlegroups.com

Please only use the ndk we supply with necessitas. We arent on r7 yet.

On Jan 9, 2012 12:34 PM, "ASM" <asm...@gmail.com> wrote:

ASM

unread,
Jan 9, 2012, 10:36:43 AM1/9/12
to andro...@googlegroups.com
Hello,

Thank you for replay.

It may sound silly, but there is no NDK without revision (without 'rx' x is number)..  there is only:

http://developer.android.com/sdk/ndk/index.html


 Android NDK, Revision 6b (August 2011)
 Android NDK, Revision 6 (July 2011)
 Android NDK, Revision 5c (June 2011)
 Android NDK, Revision 5b (January 2011)
 Android NDK, Revision 5 (December 2010)
 Android NDK, Revision 4b (June 2010)
 Android NDK, Revision 3 (March 2010)


Or maybe I misunderstood something?


Best regards,
AS

Tyler Mandry

unread,
Jan 9, 2012, 12:36:04 PM1/9/12
to andro...@googlegroups.com
He's saying to use the NDK that comes with the necessitas download. It should be found within the necessitas directory. I believe it's r6b (but don't take my word for it.)
--
Tyler Mandry

mingw android

unread,
Jan 9, 2012, 12:46:43 PM1/9/12
to andro...@googlegroups.com

That's right. We supply our own modified version of the ndk, and we are currently on r6b.

ASM

unread,
Jan 9, 2012, 2:56:57 PM1/9/12
to andro...@googlegroups.com
Thank you.. I've fixed it..

But have the same problem:
I have simple function related to button:



void MainWindow::on_pushButton_clicked()
{

 //callback_handler((char *) "Called from native thread");

       JNIEnv *env;
       JavaVMInitArgs args;


       args.version = JNI_VERSION_1_2;
       args.nOptions = 0;
       args.ignoreUnrecognized = JNI_FALSE;

        vm->AttachCurrentThread(&env, NULL);


 ui->textEdit->append(QString(getPropertyValue(env, "java.version")));
 ui->textEdit->append( QString(getPropertyValue(env, "java.vendor")));

           vm->DestroyJavaVM();

}



and Function:




const char *getPropertyValue(JNIEnv *env, const char *name)
{
    // Calling System.getProperty(propertyName);
    jclass systemClass = env->FindClass("java/lang/System");
    jmethodID getPropertyMethod = env->GetStaticMethodID(systemClass, "getProperty",
                                                        "(Ljava/lang/String;)Ljava/lang/String;");

    jstring propertyName = env->NewStringUTF(name);
    jstring value = (jstring) env->CallStaticObjectMethod(systemClass,
                                                          getPropertyMethod,
                                                          propertyName);

    return env->GetStringUTFChars(value, NULL);
}


It should return java version and vendor by clicking button.

I am able to compile it only when:

        vm->AttachCurrentThread(&env, NULL);

But I always get segmentation fault executing software in android emulator when I press Pushbutton.

According some examples there should bused (void **)&env  :

  vm->AttachCurrentThread((void **)&env, NULL);  // here used (void **)

but with it an error appears:

/home/darka/ProgramFiles/QT_work/Android/JNI_1/test_JNI-build--Necessitas_Qt_4_8_0_for_Android_API_4__armv5_Debug/../test_JNI/mainwindow.cpp:95: error: invalid conversion from 'void**' to 'JNIEnv**'

What am I doing wrong???


Best regards,
AS

Tyler Mandry

unread,
Jan 9, 2012, 3:55:35 PM1/9/12
to andro...@googlegroups.com
I assume you initialize vm somewhere, such as in JNI_OnLoad?

To start, you should NEVER be calling DestroyJavaVM(). This is only if you create your own VM, which you haven't. Perhaps you want DetachCurrentThread()?
--
Tyler Mandry

ASM

unread,
Jan 10, 2012, 7:01:04 AM1/10/12
to andro...@googlegroups.com
Actually I am declaring globally:  JavaVM *vm;
so et the end of program I should destroy it.


Is there global already created VM? How to reach it?

Tyler Mandry

unread,
Jan 11, 2012, 5:06:34 PM1/11/12
to andro...@googlegroups.com
Oh no.. simply declaring a pointer does not create a virtual machine, or give you a reference to the existing one.

The correct/best way to get the vm reference is to define a JNI_OnLoad() function that gets exported. Java will call that when it loads your library.

--
Tyler Mandry

Juan Manuel Sáez

unread,
Jan 12, 2012, 3:58:16 AM1/12/12
to andro...@googlegroups.com
Hello:

Im interested in this thread because in my project I must register a new C function to be used from the java part. I tried to create the JNI_OnLoad() function in my code (under mainwindow.cpp for example) but I can't compile because this function is already defined. Possibly, the conflict cames from the libraries of necessitas that I am loading, because each module contains its own JNI_OnLoad() function, as I can see in the sources. Then, how can I create this function? In a separate lib or similar?

Thanks in advance.

JMSaez

2012/1/11 Tyler Mandry <tma...@gmail.com>



--
______________________________________________________

Dr. Juan Manuel Sáez Martínez
Profesor Titular de Universidad
Departamento de Ciencia de la Computación e Inteligencia Artificial
Escuela Politécnica Superior. Universidad de Alicante
Teléfono: 965903900 ext 2752 Fax: 965903902
______________________________________________________

ASM

unread,
Jan 12, 2012, 2:03:01 PM1/12/12
to andro...@googlegroups.com
Thank you for replay.. I have some progress but faced with another one:

When I declare globally:   JavaVM *m_javaVM;

then function bellow returns: "Unable to get JVM"
 

void MainWindow::on_pushButton_clicked()
{     if (!m_javaVM)
     {         ui->textEdit->append("Unable to get JVM" );            
     }else  ui->textEdit->append("Able to get JVM" );
}

But when I declare locally:


void MainWindow::on_pushButton_clicked()
{    JavaVM *m_javaVM;                                  <<-- declaration

  if (!m_javaVM)
     {         ui->textEdit->append("Unable to get JVM" );            
     }else  ui->textEdit->append("Able to get JVM" );
}


then function return: "Able to get JVM"

Accordint some examples on internet globar declaration of JavaVM *m_javaVM;
should work and seems that I need it if I want to use it with threads.

Sorry for silly question!!

Best regards,
AS

Tyler Mandry

unread,
Jan 12, 2012, 11:49:37 PM1/12/12
to andro...@googlegroups.com
A global is what you need to use, and will work **if you initialize it first**, like in JNI_OnLoad() as I said, which gets passed a JavaVM* that you can use in your code. The examples on the internet may not be complete. All you seem to be doing here is comparing an uninitialized pointer value to 0. The results, of course, are undefined. (If you don't understand what I'm saying, you probably need to buy a C/C++ book, and I would recommend staying away from JNI for awhile; it's very tricky.)
--
Tyler Mandry

ASM

unread,
Jan 13, 2012, 3:12:52 AM1/13/12
to andro...@googlegroups.com
JNI_OnLoad() is already defined in qtmain_android.cpp :

Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
{
    __android_log_print(ANDROID_LOG_INFO,"Qt", "qt start");
    UnionJNIEnvToVoid uenv;
    uenv.venv = NULL;
    m_javaVM = 0;

    if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK)
    {
        __android_log_print(ANDROID_LOG_FATAL,"Qt","GetEnv failed");
        return -1;
    }
    m_env = uenv.nativeEnvironment;
    if (!registerNatives(m_env))
    {
        __android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
        return -1;
    }
    m_javaVM = vm;
    return JNI_VERSION_1_4;
}

I tried to declare JavaVM externaly, because is already declared in and initilaized in qtmain_android.cpp
results the same..

Imitation of such initialization does not helpping.. always I get segmentation fault on GetEnv()


It seems that I need simple full project example that initialize JNI by pressing button..


Best regards,
AS

Tyler Mandry

unread,
Jan 13, 2012, 3:24:12 AM1/13/12
to andro...@googlegroups.com
Oh yes I see... sorry if I insulted you :) Did you declare it with "extern"? You would need

extern Java_VM *m_javaVM;

(Also, if it's declared as "static" in qtmain_android you can't do anything to get the value.) If that's not it then I'm not sure why it would remain uninitialized.

(Sorry about the previous reply; I'm thinking in terms of my patch which separates out qtmain_android from the rest of the application library. But it's not applied yet.)
--
Tyler Mandry

ASM

unread,
Jan 13, 2012, 3:45:09 AM1/13/12
to andro...@googlegroups.com
No problem!  :)
I am confused by my self..

 I tried:   extern Java_VM *m_javaVM;

But results are the same, by this reason I applied to forum.

I am not successful almost week and desperate trying everything and nothing ...  :(


Actually I am not quite sure which jni.h I should use, at the moment I am using:
#include   </home/darka/ProgramFiles/necessitas/android-ndk-r6b/platforms/android-9/arch-arm/usr/include/jni.h>


I use: #include "jni.h" 
this file cannot be found until in .pro file I add


JAVA_HOME = /usr/lib/jvm/java-1.6.0-openjdk
INCLUDEPATH += $$JAVA_HOME/include
INCLUDEPATH += $$JAVA_HOME/include/linux


(this one was at first time I tried to compile for android) but java on linux is not I need.. I suppose need to use some jni.h (for android) that available in necessitas directory (there are sevel jni.h files in ncessitas).

Best regards,
AS
Reply all
Reply to author
Forward
0 new messages