summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAssam Boudjelthia <assam.boudjelthia@qt.io>2020-03-04 16:26:51 +0200
committerAssam Boudjelthia <assam.boudjelthia@qt.io>2020-03-12 19:07:18 +0200
commitfe69fb5371b193288fcb1b38d70c9fd4ac4fd74a (patch)
treea575b5b298c097940ea60891b24559799b2a5e62
parenta55cae70165206bd2a04306291fb3442968b69c3 (diff)
Introduce new example JNI Messenger
This examples shows the proper way to communication between QML/C++ and Java in both ways. This example calls a Java method from QML and C++, then the Java method will also call back a C++ function that will be forwarded to a QML connection. Task-number: QTBUG-80717 Change-Id: I96d9551d1abcaf80899c4dd3c727a267fb6f3c07 Reviewed-by: BogDan Vatra <bogdan@kdab.com>
-rw-r--r--examples/androidextras/androidextras.pro9
-rw-r--r--examples/androidextras/jnimessenger/android/AndroidManifest.xml87
-rw-r--r--examples/androidextras/jnimessenger/android/res/drawable-hdpi/icon.pngbin0 -> 3654 bytes
-rw-r--r--examples/androidextras/jnimessenger/android/res/drawable-ldpi/icon.pngbin0 -> 1432 bytes
-rw-r--r--examples/androidextras/jnimessenger/android/res/drawable-mdpi/icon.pngbin0 -> 1998 bytes
-rw-r--r--examples/androidextras/jnimessenger/android/res/drawable-xhdpi/icon.pngbin0 -> 4549 bytes
-rw-r--r--examples/androidextras/jnimessenger/android/res/drawable-xxhdpi/icon.pngbin0 -> 9275 bytes
-rw-r--r--examples/androidextras/jnimessenger/android/res/drawable-xxxhdpi/icon.pngbin0 -> 12866 bytes
-rw-r--r--examples/androidextras/jnimessenger/android/src/org/qtproject/example/jnimessenger/JniMessenger.java64
-rw-r--r--examples/androidextras/jnimessenger/doc/src/qtandroidextras-example-jnimessenger.qdoc145
-rw-r--r--examples/androidextras/jnimessenger/jnimessenger.cpp86
-rw-r--r--examples/androidextras/jnimessenger/jnimessenger.h74
-rw-r--r--examples/androidextras/jnimessenger/jnimessenger.pro21
-rw-r--r--examples/androidextras/jnimessenger/main.cpp76
-rw-r--r--examples/androidextras/jnimessenger/main.qml103
-rw-r--r--examples/androidextras/jnimessenger/qml.qrc5
-rw-r--r--src/androidextras/doc/images/jnimessenger.pngbin0 -> 34630 bytes
17 files changed, 668 insertions, 2 deletions
diff --git a/examples/androidextras/androidextras.pro b/examples/androidextras/androidextras.pro
index ce3926f..7239503 100644
--- a/examples/androidextras/androidextras.pro
+++ b/examples/androidextras/androidextras.pro
@@ -1,7 +1,12 @@
TEMPLATE = subdirs
android {
qtHaveModule(quick) {
- SUBDIRS += notification
- EXAMPLE_FILES += notification
+ SUBDIRS += \
+ notification \
+ jnimessenger
+
+ EXAMPLE_FILES += \
+ notification \
+ jnimessenger
}
}
diff --git a/examples/androidextras/jnimessenger/android/AndroidManifest.xml b/examples/androidextras/jnimessenger/android/AndroidManifest.xml
new file mode 100644
index 0000000..56617c4
--- /dev/null
+++ b/examples/androidextras/jnimessenger/android/AndroidManifest.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0"?>
+<manifest package="org.qtproject.example.jnimessenger" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
+
+ <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
+ Remove the comment if you do not require these default permissions. -->
+ <!-- %%INSERT_PERMISSIONS -->
+
+ <!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
+ Remove the comment if you do not require these default features. -->
+ <!-- %%INSERT_FEATURES -->
+
+ <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
+
+ <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Qt JNI Messenger" android:extractNativeLibs="true" android:icon="@drawable/icon">
+ <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="unspecified" android:launchMode="singleTop">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+
+ <!-- Application arguments -->
+ <!-- meta-data android:name="android.app.arguments" android:value="arg1 arg2 arg3"/ -->
+ <!-- Application arguments -->
+
+ <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
+ <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
+ <meta-data android:name="android.app.repository" android:value="default"/>
+ <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
+ <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
+ <!-- Deploy Qt libs as part of package -->
+ <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
+
+ <!-- Run with local libs -->
+ <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
+ <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
+ <meta-data android:name="android.app.load_local_libs_resource_id" android:resource="@array/load_local_libs"/>
+ <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
+ <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
+ <!-- Used to specify custom system library path to run with local system libs -->
+ <!-- <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/> -->
+ <!-- Messages maps -->
+ <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
+ <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
+ <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
+ <meta-data android:value="@string/unsupported_android_version" android:name="android.app.unsupported_android_version"/>
+ <!-- Messages maps -->
+
+ <!-- Splash screen -->
+ <!-- Orientation-specific (portrait/landscape) data is checked first. If not available for current orientation,
+ then android.app.splash_screen_drawable. For best results, use together with splash_screen_sticky and
+ use hideSplashScreen() with a fade-out animation from Qt Android Extras to hide the splash screen when you
+ are done populating your window with content. -->
+ <!-- meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/logo_portrait" / -->
+ <!-- meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/logo_landscape" / -->
+ <!-- meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/ -->
+ <!-- meta-data android:name="android.app.splash_screen_sticky" android:value="true"/ -->
+ <!-- Splash screen -->
+
+ <!-- Background running -->
+ <!-- Warning: changing this value to true may cause unexpected crashes if the
+ application still try to draw after
+ "applicationStateChanged(Qt::ApplicationSuspended)"
+ signal is sent! -->
+ <meta-data android:name="android.app.background_running" android:value="false"/>
+ <!-- Background running -->
+
+ <!-- auto screen scale factor -->
+ <meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
+ <!-- auto screen scale factor -->
+
+ <!-- extract android style -->
+ <!-- available android:values :
+ * default - In most cases this will be the same as "full", but it can also be something else if needed, e.g., for compatibility reasons
+ * full - useful QWidget & Quick Controls 1 apps
+ * minimal - useful for Quick Controls 2 apps, it is much faster than "full"
+ * none - useful for apps that don't use any of the above Qt modules
+ -->
+ <meta-data android:name="android.app.extract_android_style" android:value="default"/>
+ <!-- extract android style -->
+ </activity>
+
+ <!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
+
+ </application>
+
+</manifest>
diff --git a/examples/androidextras/jnimessenger/android/res/drawable-hdpi/icon.png b/examples/androidextras/jnimessenger/android/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..d3ccebe
--- /dev/null
+++ b/examples/androidextras/jnimessenger/android/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/examples/androidextras/jnimessenger/android/res/drawable-ldpi/icon.png b/examples/androidextras/jnimessenger/android/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..2194be1
--- /dev/null
+++ b/examples/androidextras/jnimessenger/android/res/drawable-ldpi/icon.png
Binary files differ
diff --git a/examples/androidextras/jnimessenger/android/res/drawable-mdpi/icon.png b/examples/androidextras/jnimessenger/android/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..31812cc
--- /dev/null
+++ b/examples/androidextras/jnimessenger/android/res/drawable-mdpi/icon.png
Binary files differ
diff --git a/examples/androidextras/jnimessenger/android/res/drawable-xhdpi/icon.png b/examples/androidextras/jnimessenger/android/res/drawable-xhdpi/icon.png
new file mode 100644
index 0000000..3aeae64
--- /dev/null
+++ b/examples/androidextras/jnimessenger/android/res/drawable-xhdpi/icon.png
Binary files differ
diff --git a/examples/androidextras/jnimessenger/android/res/drawable-xxhdpi/icon.png b/examples/androidextras/jnimessenger/android/res/drawable-xxhdpi/icon.png
new file mode 100644
index 0000000..f754fd1
--- /dev/null
+++ b/examples/androidextras/jnimessenger/android/res/drawable-xxhdpi/icon.png
Binary files differ
diff --git a/examples/androidextras/jnimessenger/android/res/drawable-xxxhdpi/icon.png b/examples/androidextras/jnimessenger/android/res/drawable-xxxhdpi/icon.png
new file mode 100644
index 0000000..d0d043b
--- /dev/null
+++ b/examples/androidextras/jnimessenger/android/res/drawable-xxxhdpi/icon.png
Binary files differ
diff --git a/examples/androidextras/jnimessenger/android/src/org/qtproject/example/jnimessenger/JniMessenger.java b/examples/androidextras/jnimessenger/android/src/org/qtproject/example/jnimessenger/JniMessenger.java
new file mode 100644
index 0000000..e3b7408
--- /dev/null
+++ b/examples/androidextras/jnimessenger/android/src/org/qtproject/example/jnimessenger/JniMessenger.java
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtAndroidExtras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+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!");
+ }
+}
diff --git a/examples/androidextras/jnimessenger/doc/src/qtandroidextras-example-jnimessenger.qdoc b/examples/androidextras/jnimessenger/doc/src/qtandroidextras-example-jnimessenger.qdoc
new file mode 100644
index 0000000..ddebcce
--- /dev/null
+++ b/examples/androidextras/jnimessenger/doc/src/qtandroidextras-example-jnimessenger.qdoc
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtAndroidExtras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \title Qt JNI Messenger
+ \ingroup examples-qtandroidextras
+ \example jnimessenger
+ \brief Demonstrates communication between Java code and QML or C++ using NJI calls.
+
+ \image jnimessenger.png
+
+ 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:
+
+ \badcode
+ 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!
+ \endcode
+
+ \include examples-run.qdocinc
+
+ \section1 Calling Java Methods from C++ Code
+
+ We define a custom Java class called \c JniMessenger in the JniMessenger.java file:
+
+ \quotefromfile jnimessenger/android/src/org/qtproject/example/jnimessenger/JniMessenger.java
+ \skipto org.qtproject.example.jnimessenger
+ \printuntil /^\}/
+
+ \note 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 \c printFromJava(String message)
+ by first creating a \c QAndroidJniObject for the Java String that we want to send
+ and then invoking a JNI call with \c callStaticMethod<>() while providing the method
+ signature:
+
+ \quotefromfile jnimessenger/jnimessenger.cpp
+ \skipto void JniMessenger::printFromJava
+ \printuntil }
+
+ That call will then execute the following from Java side, which would print the
+ message to the \c System.output.
+
+ \quotefromfile jnimessenger/android/src/org/qtproject/example/jnimessenger/JniMessenger.java
+ \skipto public static void printFromJava
+ \printuntil );
+
+ \section2 Calling QML/C++ Functions from Java Code
+
+ Directly after that, our native function \c callFromJava(String message) will be
+ called, which would be then handled from C++ side. Note, that this method has
+ to be defined as \c native at the top of the Java class as:
+
+ \code
+ private static native void callFromJava(String message);
+ \endcode
+
+ To be able to call C++ functions from Java, in our C++ class JniMessenger.cpp,
+ we need to define those functions using \c RegisterNatives() as follows:
+
+ \quotefromfile jnimessenger/jnimessenger.cpp
+ \skipto JNINativeMethod
+ \printuntil }
+
+ (See \l{Java Native Methods} for more details).
+
+ We would need to register the functions' signatures in \c methods[], which have
+ the name in Java class, then its parameters and return types, then the function
+ pointer in the C++ code.
+
+ \code
+ JNINativeMethod methods[] {{"callFromJava", "(Ljava/lang/String;)V", reinterpret_cast<void *>(callFromJava)}};
+ \endcode
+
+ 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:
+
+ \quotefromfile jnimessenger/jnimessenger.cpp
+ \skipto static void callFromJava
+ \printuntil }
+
+ Now, we need to implement the necessary \c Connections in the QML code to receive
+ the message from C++, which we would print into the \c Text view with the id \c messengerLog:
+
+ \quotefromfile jnimessenger/main.qml
+ \skipto Connections
+ \printuntil /^\ {4}\}/
+
+ \sa {Qt for Android}, {Qt Android Extras}
+*/
diff --git a/examples/androidextras/jnimessenger/jnimessenger.cpp b/examples/androidextras/jnimessenger/jnimessenger.cpp
new file mode 100644
index 0000000..3c309ba
--- /dev/null
+++ b/examples/androidextras/jnimessenger/jnimessenger.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtAndroidExtras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "jnimessenger.h"
+
+#include <QAndroidJniObject>
+#include <QAndroidJniEnvironment>
+#include <QtAndroid>
+
+JniMessenger *JniMessenger::m_instance = nullptr;
+
+static void callFromJava(JNIEnv *env, jobject /*thiz*/, jstring value)
+{
+ emit JniMessenger::instance()->messageFromJava(env->GetStringUTFChars(value, nullptr));
+}
+
+JniMessenger::JniMessenger(QObject *parent) : QObject(parent)
+{
+ m_instance = this;
+
+ JNINativeMethod methods[] {{"callFromJava", "(Ljava/lang/String;)V", reinterpret_cast<void *>(callFromJava)}};
+ QAndroidJniObject javaClass("org/qtproject/example/jnimessenger/JniMessenger");
+
+ QAndroidJniEnvironment env;
+ jclass objectClass = env->GetObjectClass(javaClass.object<jobject>());
+ env->RegisterNatives(objectClass,
+ methods,
+ sizeof(methods) / sizeof(methods[0]));
+ env->DeleteLocalRef(objectClass);
+}
+
+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>());
+}
diff --git a/examples/androidextras/jnimessenger/jnimessenger.h b/examples/androidextras/jnimessenger/jnimessenger.h
new file mode 100644
index 0000000..441e476
--- /dev/null
+++ b/examples/androidextras/jnimessenger/jnimessenger.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtAndroidExtras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MYCLASS_H
+#define MYCLASS_H
+
+#include <QObject>
+
+class JniMessenger : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit JniMessenger(QObject *parent = nullptr);
+ static JniMessenger *instance() { return m_instance; }
+ Q_INVOKABLE void printFromJava(const QString &message);
+
+signals:
+ void messageFromJava(const QString &message);
+
+public slots:
+
+private:
+ static JniMessenger *m_instance;
+};
+
+#endif // MYCLASS_H
diff --git a/examples/androidextras/jnimessenger/jnimessenger.pro b/examples/androidextras/jnimessenger/jnimessenger.pro
new file mode 100644
index 0000000..b1a6326
--- /dev/null
+++ b/examples/androidextras/jnimessenger/jnimessenger.pro
@@ -0,0 +1,21 @@
+QT += quick androidextras
+
+DEFINES += QT_DEPRECATED_WARNINGS
+
+SOURCES += \
+ jnimessenger.cpp \
+ main.cpp
+
+HEADERS += \
+ jnimessenger.h
+
+RESOURCES += qml.qrc
+
+ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
+DISTFILES += \
+ android/src/org/qtproject/example/jnimessenger/JniMessenger.java \
+ android/AndroidManifest.xml
+
+
+target.path = $$[QT_INSTALL_EXAMPLES]/androidextras/jnimessenger
+INSTALLS += target
diff --git a/examples/androidextras/jnimessenger/main.cpp b/examples/androidextras/jnimessenger/main.cpp
new file mode 100644
index 0000000..45e914a
--- /dev/null
+++ b/examples/androidextras/jnimessenger/main.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtAndroidExtras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "jnimessenger.h"
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QQmlContext>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QQmlApplicationEngine engine;
+ const QUrl url(QStringLiteral("qrc:/main.qml"));
+
+ JniMessenger *jniMessenger = new JniMessenger(&app);
+
+ engine.rootContext()->setContextProperty(QLatin1String("JniMessenger"), jniMessenger);
+
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
+ &app, [url](QObject *obj, const QUrl &objUrl) {
+ if (!obj && url == objUrl)
+ QCoreApplication::exit(-1);
+ }, Qt::QueuedConnection);
+ engine.load(url);
+
+ return app.exec();
+}
diff --git a/examples/androidextras/jnimessenger/main.qml b/examples/androidextras/jnimessenger/main.qml
new file mode 100644
index 0000000..57c90ec
--- /dev/null
+++ b/examples/androidextras/jnimessenger/main.qml
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtAndroidExtras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.13
+import QtQuick.Window 2.13
+import QtQuick.Controls 2.13
+import QtQuick.Layouts 1.13
+
+ApplicationWindow {
+ id: window
+ visible: true
+
+ ColumnLayout {
+ anchors.fill: parent
+ Text {
+ id: messengerLog
+ text: qsTr("")
+ clip: true
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ transformOrigin: Item.Center
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
+ }
+
+ RowLayout {
+ id: rowlayout
+ Layout.bottomMargin: 10
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
+ anchors.bottom: window.bottom
+ spacing: 10
+
+ Button {
+ text: qsTr("Send to Java via JNI")
+ onClicked: {
+ var message = qsTr("QML sending to Java: Hello from QML")
+ messengerLog.text += "\n" + message
+ JniMessenger.printFromJava(message)
+ }
+ }
+
+ Button {
+ text: "Clear"
+ onClicked: messengerLog.text = ""
+ }
+ }
+ }
+
+ Connections {
+ target: JniMessenger
+ function onMessageFromJava(message) {
+ var output = qsTr("QML received a message: %1").arg(message)
+ print(output)
+ messengerLog.text += "\n" + output
+ }
+ }
+}
diff --git a/examples/androidextras/jnimessenger/qml.qrc b/examples/androidextras/jnimessenger/qml.qrc
new file mode 100644
index 0000000..5f6483a
--- /dev/null
+++ b/examples/androidextras/jnimessenger/qml.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/src/androidextras/doc/images/jnimessenger.png b/src/androidextras/doc/images/jnimessenger.png
new file mode 100644
index 0000000..1cb4efd
--- /dev/null
+++ b/src/androidextras/doc/images/jnimessenger.png
Binary files differ