Qt JNI Messenger

Demonstrates communication between Java code and QML or C++ using NJI calls.

This example demonstrates how to add a custom Java class to an Android application, and how to both call it from C++ and call C++ functions from Java using the JNI convenience APIs in the Qt Android Extras module. The application UI is created by using Qt Quick.

When clicking the send button, a message will be sent from QML to Java class though the C++ class and a log of that is shown in the screen view. Logs also can be seen from the Android logcat of the messages being exchanged, which would be similar to:

I System.out: This is printed from JAVA, message is: QML sending to Java: Hello from QML
D libjnimessenger_armeabi-v7a.so: qml: QML received a message: Hello from JAVA!
					
					

运行范例

要运行范例从 Qt Creator ,打开 欢迎 模式,然后选择范例从 范例 。更多信息,拜访 构建和运行范例 .

从 C++ 代码调用 Java 方法

We define a custom Java class called JniMessenger in the JniMessenger.java file:

package org.qtproject.example.jnimessenger;
public class JniMessenger
{
    private static native void callFromJava(String message);
    public JniMessenger() {}
    public static void printFromJava(String message)
    {
        System.out.println("This is printed from JAVA, message is: " + message);
        callFromJava("Hello from JAVA!");
    }
}
					

注意: The custom Java class can extend other classes like QtActivity, Activity or any other Java class.

In the jnimessenger.cpp file, we call the function printFromJava(String message) by first creating a QAndroidJniObject for the Java String that we want to send and then invoking a JNI call with callStaticMethod<>() while providing the method signature:

void JniMessenger::printFromJava(const QString &message)
{
    QAndroidJniObject javaMessage = QAndroidJniObject::fromString(message);
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/jnimessenger/JniMessenger",
                                       "printFromJava",
                                       "(Ljava/lang/String;)V",
                                        javaMessage.object<jstring>());
}
					

That call will then execute the following from Java side, which would print the message to the System.output .

    public static void printFromJava(String message)
    {
        System.out.println("This is printed from JAVA, message is: " + message);
					
					

Calling QML/C++ Functions from Java Code

Directly after that, our native function callFromJava(String message) will be called, which would be then handled from C++ side. Note, that this method has to be defined as native at the top of the Java class as:

private static native void callFromJava(String message);
					

To be able to call C++ functions from Java, in our C++ class JniMessenger.cpp, we need to define those functions using RegisterNatives() 如下:

    JNINativeMethod methods[] {{"callFromJava", "(Ljava/lang/String;)V", reinterpret_cast<void *>(callFromJava)}};
					

(见 Java 本机方法 了解更多细节)。

We would need to register the functions' signatures in methods[] , which have the name in Java class, then its parameters and return types, then the function pointer in the C++ code.

JNINativeMethod methods[] {{"callFromJava", "(Ljava/lang/String;)V", reinterpret_cast<void *>(callFromJava)}};
					

This would insure that our C++ function is available from within the Java call. Now, that function could simply print the message it received from Java to the debug log, but we want to forward the received message to the QML components so that it gets displayed in our text view, so we get:

static void callFromJava(JNIEnv *env, jobject /*thiz*/, jstring value)
{
    emit JniMessenger::instance()->messageFromJava(env->GetStringUTFChars(value, nullptr));
}
					

Now, we need to implement the necessary Connections in the QML code to receive the message from C++, which we would print into the 文本 view with the id messengerLog :

    Connections {
        target: JniMessenger
        function onMessageFromJava(message) {
            var output = qsTr("QML received a message: %1").arg(message)
            print(output)
            messengerLog.text += "\n" + output
        }
    }
					

范例工程 @ code.qt.io

另请参阅 Qt for Android and Qt Android Extras .