Passing strings from java to C ++ using JNI

I have an Android app that receives unread notifications from Facebook and Inbox. The application should be executed in QT, but I almost do not know QT C ++, so I developed the application in java and just call the java class from QT using JNI. This works fine, but the fact is that I need to send a slot (on the QT side) every time a new Facebook notification / message appears.

So my question is: every minute, How to notify QT from Java that I have a new message and send a line?

This is my Java code:

MAIN CLASS:

public class MainActivity extends FragmentActivity { ... static public void startFacebookActivity() { String msgTag = "FACEBOOK_APP"; try { Activity mother = QtNative.activity(); Intent intent = new Intent(mother, MainActivity.class); mother.startActivity(intent); } catch (Exception e) { Log.e(msgTag, e.toString()); e.printStackTrace(); } } } 

FRAGMENT CLASS (every minute checks if there is a new message on facebook, if so, it is assumed that he must notify QT and send a message so that QT can send a slot)

 private static native void publishNotification(String notification); .... if (newNotification==true) publishNotification(responseNotification); ... 

QT side

facebookAndroid.cpp

 #include "facebookAndroid.h" #include <QtAndroidExtras> FacebookAndroid* FacebookAndroid::s_instance = 0; FacebookAndroid::FacebookAndroid(QObject *parent) : QObject(parent) { s_instance = this;} void FacebookAndroid::startAndroidFacebook() { QAndroidJniObject::callStaticMethod<void>("org.qtproject.example.MainActivity", "startFacebookActivity", "()V"); } FacebookAndroid* FacebookAndroid::instance() { return s_instance; } static void publishNotification(JNIEnv *env, jclass /*clazz*/, jstring notification) { const char* nativeString = env->GetStringUTFChars(notification, 0); FacebookAndroid::instance()->handleNewNotification(QString(nativeString)); } static JNINativeMethod methods[] = { {"publishNotification", "(Ljava/lang/String;)V", (void *)publishNotification} }; jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { JNIEnv *env; if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4) != JNI_OK) return JNI_FALSE; jclass clazz = env->FindClass("org/qtproject/example/MainActivity"); if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) return JNI_FALSE; return JNI_VERSION_1_4; } 

main.cpp

  #include <QtGui/QGuiApplication> #include "qtquick2applicationviewer.h" #include <QtQuick> #include "facebookAndroid.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QtQuick2ApplicationViewer viewer; FacebookAndroid sa(&viewer); viewer.rootContext()->setContextProperty(QString("iniciaFacebook"), &sa); viewer.setMainQmlFile(QStringLiteral("qml/FacebookTry/main.qml")); viewer.showExpanded(); return app.exec(); } 

facebookAndroid.h

  #ifndef FACEBOOKANDROID_H #define FACEBOOKANDROID_H #include <QObject> #include <jni.h> class FacebookAndroid : public QObject { Q_OBJECT public: FacebookAndroid(QObject *parent = 0); FacebookAndroid* instance(); void handleNewNotification(QString notification); protected: static FacebookAndroid *s_instance; public slots: void startAndroidFacebook(); }; #endif // FACEBOOKANDROID_H 

BUILDING ERRORS

 In function 'void publisNotification(JNIEnv*, jclass,jstring)' cannot call member function 'FacebookAnddroid::instance()' without object FacebookAndroid::instance()->handleNewNotification(QString(nativeString)); in facebookAndroid.cpp 

any help would be very helpful

+6
source share
3 answers

If I did this, I would probably choose this path:

  • Define your own Java method. It will be used as your "signal" by Java.
  • Implement a C ++ implementation for your own method. Manipulate the instance to be advertised (slot owner)
  • Register your own method

In your Java class:

 class Main Activity { // ... private static native void publishNotification(String notification); // Call it from your Java code as it has a proper implementation //... if (newNotification) { publishNotification(notification); } //... 

On the C ++ / Qt side:

Singleton implementation:

 //in facebookandroid.h class FacebookAndroid { public: FacebookAndroid* instance(); void handleNewNotification(QString notification); protected: static FacebookAndroid *s_instance; }; //in facebookandroid.cpp FacebookAndroid* FacebookAndroid::s_instance = 0; FacebookAndroid::FacebookAndroid(QObject *parent) : QObject(parent) { s_instance = this; // remind your first instanciation here } FacebookAndroid* FacebookAndroid::instance() { return s_instance; } 

Implementation of the native method:

 //In facebookandroid.cpp static void publishNotifcation(JNIEnv *env, jclass /*clazz*/, jstring notification) { const char* nativeString = env->GetStringUTFChars(notification, 0); FacebookAndroid::instance()->handleNewNotification(QString(nativeString)); } 

As we can only do this with the static method, I have to define a singleton from my class to access only one instance in particular.

Method registration:

 //In facebookandroid.cpp static JNINativeMethod methods[] = { {"publishNotification", "(Ljava/lang/String;)V", (void *)publishNotification} }; jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { JNIEnv *env; if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4) != JNI_OK) return JNI_FALSE; jclass clazz = env->FindClass("org/qtproject/example/MainActivity"); if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) return JNI_FALSE; return JNI_VERSION_1_4; } 

After some research, I found a particularly useful and complete example . His goal is to make an InApp purchase, but the mechanism is exactly the same as I will describe in this answer.

+2
source

Since you periodically check notifications in Java, is it possible to periodically call a Java class from Qt / C ++, which then receives the data. This can be easily done with QTimer, and I see that you have already implemented the java class call from Qt.

0
source

I think RegisterNatives is the key here:

http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp17734

 static void sendToQT(JNIEnv *env, jclass clazz, jstring notification) { const char *GotInQTTheNotification = (*env)->GetStringUTFChars(env, notification, NULL); printf("Hello %s\n", GotInQTTheNotification ); (*env)->ReleaseStringUTFChars(env, notification, GotInQTTheNotification ); } } static JNINativeMethod method_table[] = { { "sendToQT", "(Ljava/lang/String;I)V", (void *) sendToQT } }; int main(int argc, char *argv[]) { JavaVM *vm; JNIEnv *env; /* * more of code */ jclass clazz = (*env)->FindClass(env, "org/qtproject/example/MainActivity"); jint ret = (*env)->RegisterNatives(env, clazz, method_table, method_table_size); vm->DestroyJavaVM(); return 0; } 

Include your own ad in your MainAcitivty.java.

 public static void native sendToQT(String notification); 
0
source

Source: https://habr.com/ru/post/973431/


All Articles