Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
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{
71 return QtAndroidPrivate::activity().isValid();
72}
73
81int QNativeInterface::QAndroidApplication::sdkVersion()
82{
84}
85
95void QNativeInterface::QAndroidApplication::hideSplashScreen(int duration)
96{
97 QtAndroidPrivate::activity().callMethod<void>("hideSplashScreen", duration);
98}
99
160#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
161QFuture<QVariant> QNativeInterface::QAndroidApplication::runOnAndroidMainThread(
162 const std::function<QVariant()> &runnable,
164{
165 auto promise = std::make_shared<QPromise<QVariant>>();
166 QFuture<QVariant> future = promise->future();
167 promise->start();
168
169 if (!timeout.isForever()) {
170 QThreadPool::globalInstance()->start([=]() mutable {
171 QEventLoop loop;
172 QTimer::singleShot(timeout.remainingTime(), &loop, [&]() {
173 future.cancel();
174 promise->finish();
175 loop.quit();
176 });
177
178 QFutureWatcher<QVariant> watcher;
180 loop.quit();
181 });
183 loop.quit();
184 });
185 watcher.setFuture(future);
186
187 // we're going to sleep, make sure we don't block
188 // QThreadPool::globalInstance():
189
190 QThreadPool::globalInstance()->releaseThread();
191 const auto sg = qScopeGuard([] {
192 QThreadPool::globalInstance()->reserveThread();
193 });
194 loop.exec();
195 });
196 }
197
198 QMutexLocker locker(&g_pendingRunnablesMutex);
199#ifdef __cpp_aggregate_paren_init
200 g_pendingRunnables->emplace_back(runnable, std::move(promise));
201#else
202 g_pendingRunnables->push_back({runnable, std::move(promise)});
203#endif
204 locker.unlock();
205
206 QJniObject::callStaticMethod<void>(qtNativeClassName,
207 "runPendingCppRunnablesOnAndroidThread",
208 "()V");
209 return future;
210}
211
212// function called from Java from Android UI thread
213static void runPendingCppRunnables(JNIEnv */*env*/, jobject /*obj*/)
214{
215 // run all posted runnables
216 for (;;) {
217 QMutexLocker locker(&g_pendingRunnablesMutex);
218 if (g_pendingRunnables->empty())
219 break;
220
221 PendingRunnable r = std::move(g_pendingRunnables->front());
222 g_pendingRunnables->pop_front();
223 locker.unlock();
224
225 // run the runnable outside the sync block!
226 if (!r.promise->isCanceled())
227 r.promise->addResult(r.function());
228 r.promise->finish();
229 }
230}
231#endif
232
234{
235#if QT_CONFIG(future) && !defined(QT_NO_QOBJECT)
236 const JNINativeMethod methods = {"runPendingCppRunnables", "()V", (void *)runPendingCppRunnables};
237 return env.registerNativeMethods(qtNativeClassName, &methods, 1);
238#else
239 return true;
240#endif
241}
242
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:313
\inmodule QtCore
Definition qmutex.h:281
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:2960
static QThreadPool * globalInstance()
Returns the global QThreadPool instance.
bool singleShot
whether the timer is a single-shot timer
Definition qtimer.h:22
\inmodule QtCore
Definition qvariant.h:65
Combined button and popup list for selecting options.
Q_CORE_EXPORT jint androidSdkVersion()
bool registerNativeInterfaceNatives(QJniEnvironment &env)
Posts the function runnable to the Android thread.
Q_CORE_EXPORT QtJniTypes::Context context()
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