Qt 6.x
The Qt SDK
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
qandroidnativeinterface.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtCore/qcoreapplication_platform.h>
5
6#include <QtCore/private/qnativeinterface_p.h>
7#include <QtCore/private/qjnihelpers_p.h>
8#include <QtCore/qjniobject.h>
9#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
10#include <QtCore/qfuture.h>
11#include <QtCore/qfuturewatcher.h>
12#include <QtCore/qpromise.h>
13#include <QtCore/qtimer.h>
14#include <QtCore/qthreadpool.h>
15#include <deque>
16#include <memory>
17#endif
18
20
21#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
22static const char qtNativeClassName[] = "org/qtproject/qt/android/QtNative";
23
24struct PendingRunnable {
25 std::function<QVariant()> function;
26 std::shared_ptr<QPromise<QVariant>> promise;
27};
28
29using PendingRunnables = std::deque<PendingRunnable>;
30Q_GLOBAL_STATIC(PendingRunnables, g_pendingRunnables);
31Q_CONSTINIT static QBasicMutex g_pendingRunnablesMutex;
32#endif
33
47
56QtJniTypes::Context QNativeInterface::QAndroidApplication::context()
57{
59}
60
69bool QNativeInterface::QAndroidApplication::isActivityContext()
70{
72}
73
81int QNativeInterface::QAndroidApplication::sdkVersion()
82{
84}
85
95void QNativeInterface::QAndroidApplication::hideSplashScreen(int duration)
96{
97 QJniObject::callStaticMethod<void>("org/qtproject/qt/android/QtNative",
98 "hideSplashScreen", "(I)V", duration);
99}
100
161#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
162QFuture<QVariant> QNativeInterface::QAndroidApplication::runOnAndroidMainThread(
163 const std::function<QVariant()> &runnable,
165{
166 auto promise = std::make_shared<QPromise<QVariant>>();
167 QFuture<QVariant> future = promise->future();
168 promise->start();
169
170 if (!timeout.isForever()) {
171 QThreadPool::globalInstance()->start([=]() mutable {
172 QEventLoop loop;
173 QTimer::singleShot(timeout.remainingTime(), &loop, [&]() {
174 future.cancel();
175 promise->finish();
176 loop.quit();
177 });
178
181 loop.quit();
182 });
184 loop.quit();
185 });
186 watcher.setFuture(future);
187
188 // we're going to sleep, make sure we don't block
189 // QThreadPool::globalInstance():
190
192 const auto sg = qScopeGuard([] {
194 });
195 loop.exec();
196 });
197 }
198
199 QMutexLocker locker(&g_pendingRunnablesMutex);
200#ifdef __cpp_aggregate_paren_init
201 g_pendingRunnables->emplace_back(runnable, std::move(promise));
202#else
203 g_pendingRunnables->push_back({runnable, std::move(promise)});
204#endif
205 locker.unlock();
206
207 QJniObject::callStaticMethod<void>(qtNativeClassName,
208 "runPendingCppRunnablesOnAndroidThread",
209 "()V");
210 return future;
211}
212
213// function called from Java from Android UI thread
214static void runPendingCppRunnables(JNIEnv */*env*/, jobject /*obj*/)
215{
216 // run all posted runnables
217 for (;;) {
218 QMutexLocker locker(&g_pendingRunnablesMutex);
219 if (g_pendingRunnables->empty())
220 break;
221
222 PendingRunnable r = std::move(g_pendingRunnables->front());
223 g_pendingRunnables->pop_front();
224 locker.unlock();
225
226 // run the runnable outside the sync block!
227 if (!r.promise->isCanceled())
228 r.promise->addResult(r.function());
229 r.promise->finish();
230 }
231}
232#endif
233
235{
236#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
237 const JNINativeMethod methods = {"runPendingCppRunnables", "()V", (void *)runPendingCppRunnables};
238 return QJniEnvironment().registerNativeMethods(qtNativeClassName, &methods, 1);
239#else
240 return true;
241#endif
242}
243
static JNINativeMethod methods[]
\inmodule QtCore
\inmodule QtCore
Definition qeventloop.h:16
int exec(ProcessEventsFlags flags=AllEvents)
Enters the main event loop and waits until exit() is called.
void quit()
Tells the event loop to exit normally.
\inmodule QtCore
\inmodule QtCore
Definition qmutex.h:317
\inmodule QtCore
Definition qmutex.h:285
Native interface to a core application on Android.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
void reserveThread()
Reserves one thread, disregarding activeThreadCount() and maxThreadCount().
void start(QRunnable *runnable, int priority=0)
Reserves a thread and uses it to run runnable, unless this thread will make the current thread count ...
static QThreadPool * globalInstance()
Returns the global QThreadPool instance.
void releaseThread()
Releases a thread previously reserved by a call to reserveThread().
bool singleShot
whether the timer is a single-shot timer
Definition qtimer.h:22
\inmodule QtCore
Definition qvariant.h:64
Combined button and popup list for selecting options.
Q_CORE_EXPORT jint androidSdkVersion()
Q_CORE_EXPORT QtJniTypes::Context context()
bool registerNativeInterfaceNatives()
Posts the function runnable to the Android thread.
Q_CORE_EXPORT QtJniTypes::Activity activity()
static const char qtNativeClassName[]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define QT_DEFINE_NATIVE_INTERFACE(...)
GLboolean r
[2]
GLbitfield GLuint64 timeout
[4]
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
QFuture< void > future
[5]
QFutureWatcher< int > watcher