Android: Implement backend register class
This class will be used by java delegates to register their supported functionalities to the Qt/C++ side. It registers two native functions: register- and unregisterBackend, which will be used by the aforementioned delegates. It will be used by C++ classes which currently use QtAndroid::qtActivityDelegate() to access a JNI object which implements all these features in one big class. Task-number: QTBUG-118874 Change-Id: I23a7e433104c20b96c08b682a96cfaec98ecb4a9 Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io> Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>bb10
parent
353dd10a1c
commit
124eaa6b22
|
|
@ -40,6 +40,7 @@ set(java_sources
|
|||
src/org/qtproject/qt/android/QtView.java
|
||||
src/org/qtproject/qt/android/QtEmbeddedViewInterface.java
|
||||
src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java
|
||||
src/org/qtproject/qt/android/BackendRegister.java
|
||||
)
|
||||
|
||||
qt_internal_add_jar(Qt${QtBase_VERSION_MAJOR}Android
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
package org.qtproject.qt.android;
|
||||
|
||||
class BackendRegister
|
||||
{
|
||||
static native void registerBackend(Class interfaceType, Object interfaceObject);
|
||||
static native void unregisterBackend(Class interfaceType);
|
||||
}
|
||||
|
|
@ -41,6 +41,7 @@ qt_internal_add_plugin(QAndroidIntegrationPlugin
|
|||
qandroidplatformwindow.cpp qandroidplatformwindow.h
|
||||
qandroidsystemlocale.cpp qandroidsystemlocale.h
|
||||
androidwindowembedding.cpp androidwindowembedding.h
|
||||
androidbackendregister.cpp androidbackendregister.h
|
||||
NO_UNITY_BUILD_SOURCES
|
||||
# Conflicting symbols and macros with androidjnimain.cpp
|
||||
# TODO: Unify the usage of FIND_AND_CHECK_CLASS, and similar
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "androidbackendregister.h"
|
||||
|
||||
#include "androidjnimain.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_LOGGING_CATEGORY(lcAndroidBackendRegister, "qt.qpa.androidbackendregister")
|
||||
|
||||
Q_DECLARE_JNI_CLASS(BackendRegister, "org/qtproject/qt/android/BackendRegister");
|
||||
|
||||
bool AndroidBackendRegister::registerNatives()
|
||||
{
|
||||
return QtJniTypes::BackendRegister::registerNativeMethods(
|
||||
{ Q_JNI_NATIVE_SCOPED_METHOD(registerBackend, AndroidBackendRegister),
|
||||
Q_JNI_NATIVE_SCOPED_METHOD(unregisterBackend, AndroidBackendRegister) });
|
||||
}
|
||||
|
||||
void AndroidBackendRegister::registerBackend(JNIEnv *, jclass, jclass interfaceClass,
|
||||
jobject interface)
|
||||
{
|
||||
if (AndroidBackendRegister *reg = QtAndroid::backendRegister()) {
|
||||
const QJniObject classObject(static_cast<jobject>(interfaceClass));
|
||||
QString name = classObject.callMethod<jstring>("getName").toString();
|
||||
name.replace('.', '/');
|
||||
|
||||
QMutexLocker lock(®->m_registerMutex);
|
||||
reg->m_register[name] = QJniObject(interface);
|
||||
} else {
|
||||
qCWarning(lcAndroidBackendRegister)
|
||||
<< "AndroidBackendRegister pointer is null, cannot register functionality";
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidBackendRegister::unregisterBackend(JNIEnv *, jclass, jclass interfaceClass)
|
||||
{
|
||||
if (AndroidBackendRegister *reg = QtAndroid::backendRegister()) {
|
||||
const QJniObject classObject(static_cast<jobject>(interfaceClass));
|
||||
QString name = classObject.callMethod<jstring>("getName").toString();
|
||||
name.replace('.', '/');
|
||||
|
||||
QMutexLocker lock(®->m_registerMutex);
|
||||
reg->m_register.remove(name);
|
||||
} else {
|
||||
qCWarning(lcAndroidBackendRegister)
|
||||
<< "AndroidBackendRegister pointer is null, cannot unregister functionality";
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef ANDROIDBACKENDREGISTER_H
|
||||
#define ANDROIDBACKENDREGISTER_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <QtCore/qjnienvironment.h>
|
||||
#include <QtCore/qjnitypes.h>
|
||||
#include <QtCore/qjniobject.h>
|
||||
|
||||
#include <QtCore/qstring.h>
|
||||
#include <QtCore/qmap.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcAndroidBackendRegister)
|
||||
|
||||
template <typename T>
|
||||
using ValidInterfaceType = std::enable_if_t<std::is_base_of_v<QtJniTypes::JObjectBase, T>, bool>;
|
||||
|
||||
class AndroidBackendRegister
|
||||
{
|
||||
public:
|
||||
static bool registerNatives();
|
||||
|
||||
template <typename T, ValidInterfaceType<T> = true>
|
||||
[[nodiscard]] T getInterface()
|
||||
{
|
||||
QMutexLocker lock(&m_registerMutex);
|
||||
return m_register.value(QString(QtJniTypes::Traits<T>::className().data()));
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
using IsObjectType =
|
||||
typename std::disjunction<std::is_base_of<QJniObject, Object>,
|
||||
std::is_base_of<QtJniTypes::JObjectBase, Object>>;
|
||||
|
||||
template <typename Interface, typename Ret, typename... Args,
|
||||
ValidInterfaceType<Interface> = true>
|
||||
auto callInterface(const char *func, Args... args)
|
||||
{
|
||||
if (const auto obj = getInterface<Interface>(); obj.isValid())
|
||||
return obj.template callMethod<Ret, Args...>(func, std::forward<Args>(args)...);
|
||||
|
||||
if constexpr (IsObjectType<Ret>::value)
|
||||
return Ret(QJniObject());
|
||||
if constexpr (!std::is_same_v<Ret, void>)
|
||||
return Ret{};
|
||||
}
|
||||
|
||||
private:
|
||||
QMutex m_registerMutex;
|
||||
QMap<QString, QJniObject> m_register;
|
||||
|
||||
static void registerBackend(JNIEnv *, jclass, jclass interfaceClass, jobject interface);
|
||||
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(registerBackend)
|
||||
static void unregisterBackend(JNIEnv *, jclass, jclass interfaceClass);
|
||||
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(unregisterBackend)
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // ANDROIDBACKENDREGISTER_H
|
||||
|
|
@ -85,7 +85,7 @@ static double m_density = 1.0;
|
|||
static AndroidAssetsFileEngineHandler *m_androidAssetsFileEngineHandler = nullptr;
|
||||
static AndroidContentFileEngineHandler *m_androidContentFileEngineHandler = nullptr;
|
||||
|
||||
|
||||
static AndroidBackendRegister *m_backendRegister = nullptr;
|
||||
|
||||
static const char m_qtTag[] = "Qt";
|
||||
static const char m_classErrorMsg[] = "Can't find class \"%s\"";
|
||||
|
|
@ -387,6 +387,11 @@ namespace QtAndroid
|
|||
return m_assets;
|
||||
}
|
||||
|
||||
AndroidBackendRegister *backendRegister()
|
||||
{
|
||||
return m_backendRegister;
|
||||
}
|
||||
|
||||
} // namespace QtAndroid
|
||||
|
||||
static jboolean startQtAndroidPlugin(JNIEnv *env, jobject /*object*/, jstring paramsString)
|
||||
|
|
@ -397,6 +402,7 @@ static jboolean startQtAndroidPlugin(JNIEnv *env, jobject /*object*/, jstring pa
|
|||
m_androidAssetsFileEngineHandler = new AndroidAssetsFileEngineHandler();
|
||||
m_androidContentFileEngineHandler = new AndroidContentFileEngineHandler();
|
||||
m_mainLibraryHnd = nullptr;
|
||||
m_backendRegister = new AndroidBackendRegister();
|
||||
|
||||
const QStringList argsList = QProcess::splitCommand(QJniObject(paramsString).toString());
|
||||
|
||||
|
|
@ -544,6 +550,8 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
|
|||
m_androidPlatformIntegration = nullptr;
|
||||
delete m_androidAssetsFileEngineHandler;
|
||||
m_androidAssetsFileEngineHandler = nullptr;
|
||||
delete m_backendRegister;
|
||||
m_backendRegister = nullptr;
|
||||
sem_post(&m_exitSemaphore);
|
||||
}
|
||||
|
||||
|
|
@ -891,7 +899,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
|
|||
|| !QtAndroidDialogHelpers::registerNatives(env)
|
||||
|| !QAndroidPlatformClipboard::registerNatives(env)
|
||||
|| !QAndroidPlatformWindow::registerNatives(env)
|
||||
|| !QtAndroidWindowEmbedding::registerNatives(env)) {
|
||||
|| !QtAndroidWindowEmbedding::registerNatives(env)
|
||||
|| !AndroidBackendRegister::registerNatives()) {
|
||||
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <QImage>
|
||||
#include <private/qjnihelpers_p.h>
|
||||
#include <QtCore/QJniObject>
|
||||
#include <androidbackendregister.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ namespace QtAndroid
|
|||
{
|
||||
QBasicMutex *platformInterfaceMutex();
|
||||
QAndroidPlatformIntegration *androidPlatformIntegration();
|
||||
AndroidBackendRegister *backendRegister();
|
||||
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration);
|
||||
void setQtThread(QThread *thread);
|
||||
void setViewVisibility(jobject view, bool visible);
|
||||
|
|
|
|||
Loading…
Reference in New Issue