Revision control

Copy as Markdown

// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\title \Q4A Language Exchange
\example platform/androidlanguageexchange
\meta tag {widgets,android}
\brief Demonstrates calling Java and Kotlin code from Qt, and Qt code from Java and Kotlin, in an Android application.
\ingroup androidplatform
\image languageexchange_initial.png {Android app showing a prompt and
two buttons labeled "Hello Kotlin!" and "Hello Java!"}
Click on one of the buttons to send a string to the Java and Kotlin
classes and get a modified string back.
\image languageexchange_response.png {Two side-by-side screenshots
showing the app response to the Hello Kotlin and Hello Java
buttons}
This example demonstrates how to add a custom Java class and a custom Kotlin
class to an Android
application, and how to call them using the JNI convenience APIs in Qt.
In the other direction, the Java class and Kotlin class call Qt functions.
\include examples-run.qdocinc
\note This example can only be run on Android devices.
\section1 Exchanging data between C++ and Java/Kotlin using Qt signals
We define a custom Java class called \c JavaExchanger in the
\c JavaExchanger.java file:
\quotefromfile platform/androidlanguageexchange/android/src/org/qtproject/example/androidlanguageexchange/JavaExchanger.java
\skipto org.qtproject.example.androidlanguageexchange
\printuntil /^\}/
We define a custom Kotlin class called \c KotlinExchanger in the
\c KotlinExchanger.kt file:
\quotefromfile platform/androidlanguageexchange/android/src/org/qtproject/example/androidlanguageexchange/KotlinExchanger.kt
\skipto org.qtproject.example.androidlanguageexchange
\printuntil /^\}/
Both of these classes take a long integer that is just a \c QObject* cast
to long, and when the \c fromCpp functions are called as a result
of calling the \c connectToCppExchanger function, they modify
the incoming string and send it back to the \c fromOther with
the long int.
In the DataExchanger C++ class header file, \c dataexchanger.h, we
declare a simple C++ API to exchange data between C++ and Kotlin/Java. It
consists of \c QObject with a \c fromCpp signal that is sent from
the C++ code as a response to the buttons, and
a \c fromOther signal that the Java/Kotlin
code uses to send a string to the C++ code, as described before.
\snippet platform/androidlanguageexchange/dataexchanger.h Qt DataExchanger Class
The call to the Java method uses \l QJniObject which relies on the Java Native
Interface (JNI) APIs to communicate with Java/Kotlin. The long integer
argument is cast back to the \c DataExchanger type, and the \c fromCpp
signal is then connected to a lambda that calls the Java/Kotlin
\c fromCpp function.
\snippet platform/androidlanguageexchange/otherlanguagehandler.cpp Registering the Java/Kotlin class as an observer for the C++ signal
The call of a native method of the Java/Kotlin class is forwarded
to the \c DataExchanger class, by again converting the long integer
to \c DataExchanger and then calling the \c fromOther signal of
that type.
\snippet platform/androidlanguageexchange/otherlanguagehandler.cpp Forwarding the Java/Kotlin call to Qt
To make sure our buttons do what they are supposed to, we add
the following code to trigger sending a string to Java/Kotlin
and to get back the modified string:
\snippet platform/androidlanguageexchange/main.cpp Connect button signals
\sa {\Q4A}
*/