JNI: pre-declare JNI classes for standard Java types

This avoids that we or users have to declare e.g. String or Uri in
several places in Qt. This also prevents problems where multiple
declarations (possibly from different headers) cause build errors.

As a drive-by, remove some unnecessary type declarations (e.g.
UriType, which had the same class string as Uri).

To ease the submodule update process, define a preprocessor symbol
that submodules can use to conditionally declare the type locally.
Once the dependency update is through, the symbol can be removed
and submodules can use the declaration from qjnitypes.h.

Change-Id: I7d96edf644a54246302b5c5cb478e66fa615e73e
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
(cherry picked from commit 457a1c973d68e705f9cf72ac72b19fc26cdb2917)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2024-06-11 16:50:40 +02:00 committed by Qt Cherry-pick Bot
parent 1adc8648c1
commit 9cb2200d4f
10 changed files with 56 additions and 49 deletions

View File

@ -13,7 +13,6 @@
QT_BEGIN_NAMESPACE
Q_DECLARE_JNI_CLASS(Environment, "android/os/Environment");
Q_DECLARE_JNI_CLASS(File, "java/io/File");
using namespace QNativeInterface;
using namespace Qt::StringLiterals;

View File

@ -32,10 +32,6 @@ typedef _jobject* jobject;
QT_BEGIN_NAMESPACE
#if defined(Q_OS_ANDROID)
Q_DECLARE_JNI_CLASS(Context, "android/content/Context")
#endif
namespace QNativeInterface
{
#if defined(Q_OS_ANDROID) || defined(Q_QDOC)

View File

@ -22,9 +22,6 @@
QT_BEGIN_NAMESPACE
Q_DECLARE_JNI_CLASS(Activity, "android/app/Activity")
Q_DECLARE_JNI_CLASS(Service, "android/app/Service")
namespace QtAndroidPrivate
{
class Q_CORE_EXPORT ActivityResultListener

View File

@ -275,6 +275,33 @@ static const JNINativeMethod Method##_method = { \
#define Q_JNI_NATIVE_SCOPED_METHOD(Method, Scope) Scope::Method##_method
// Classes for value types
Q_DECLARE_JNI_CLASS(String, "java/lang/String")
Q_DECLARE_JNI_CLASS(Integer, "java/lang/Integer");
Q_DECLARE_JNI_CLASS(Long, "java/lang/Long");
Q_DECLARE_JNI_CLASS(Double, "java/lang/Double");
Q_DECLARE_JNI_CLASS(Float, "java/lang/Float");
Q_DECLARE_JNI_CLASS(Boolean, "java/lang/Boolean");
Q_DECLARE_JNI_CLASS(Void, "java/lang/Void");
// Utility and I/O
Q_DECLARE_JNI_CLASS(UUID, "java/util/UUID")
Q_DECLARE_JNI_CLASS(ArrayList, "java/util/ArrayList")
Q_DECLARE_JNI_CLASS(HashMap, "java/util/HashMap")
Q_DECLARE_JNI_CLASS(Set, "java/util/Set")
Q_DECLARE_JNI_CLASS(File, "java/io/File");
// Android specific types
Q_DECLARE_JNI_CLASS(Uri, "android/net/Uri");
Q_DECLARE_JNI_CLASS(Parcelable, "android/os/Parcelable");
Q_DECLARE_JNI_CLASS(Context, "android/content/Context");
Q_DECLARE_JNI_CLASS(Intent, "android/content/Intent");
Q_DECLARE_JNI_CLASS(ContentResolver, "android/content/ContentResolver");
Q_DECLARE_JNI_CLASS(Activity, "android/app/Activity");
Q_DECLARE_JNI_CLASS(Service, "android/app/Service");
#define QT_DECLARE_JNI_CLASS_STANDARD_TYPES
QT_END_NAMESPACE
#endif // defined(Q_QDOC) || defined(Q_OS_ANDROID)

View File

@ -14,7 +14,6 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_JNI_CLASS(TimeZone, "java/util/TimeZone");
Q_DECLARE_JNI_CLASS(Locale, "java/util/Locale");
Q_DECLARE_JNI_CLASS(Date, "java/util/Date");
Q_DECLARE_JNI_CLASS(String, "java/lang/String")
/*
Private

View File

@ -25,7 +25,6 @@ Q_GLOBAL_STATIC(ProxyInfoObject, proxyInfoInstance)
Q_DECLARE_JNI_CLASS(QtNetwork, "org/qtproject/qt/android/network/QtNetwork")
Q_DECLARE_JNI_CLASS(ProxyInfo, "android/net/ProxyInfo")
Q_DECLARE_JNI_CLASS(String, "java/lang/String")
ProxyInfoObject::ProxyInfoObject()
{

View File

@ -16,9 +16,6 @@ QT_BEGIN_NAMESPACE
using namespace QNativeInterface;
using namespace Qt::StringLiterals;
Q_DECLARE_JNI_CLASS(ContentResolverType, "android/content/ContentResolver");
Q_DECLARE_JNI_CLASS(UriType, "android/net/Uri");
Q_DECLARE_JNI_CLASS(Uri, "android/net/Uri");
Q_DECLARE_JNI_CLASS(ParcelFileDescriptorType, "android/os/ParcelFileDescriptor");
Q_DECLARE_JNI_CLASS(CursorType, "android/database/Cursor");
@ -27,7 +24,7 @@ static QJniObject &contentResolverInstance()
static QJniObject contentResolver;
if (!contentResolver.isValid()) {
contentResolver = QJniObject(QNativeInterface::QAndroidApplication::context())
.callMethod<QtJniTypes::ContentResolverType>("getContentResolver");
.callMethod<QtJniTypes::ContentResolver>("getContentResolver");
}
return contentResolver;
@ -79,7 +76,7 @@ bool AndroidContentFileEngine::open(QIODevice::OpenMode openMode,
}
m_pfd = contentResolverInstance().callMethod<
QtJniTypes::ParcelFileDescriptorType, QtJniTypes::UriType, jstring>(
QtJniTypes::ParcelFileDescriptorType, QtJniTypes::Uri, jstring>(
"openFileDescriptor",
m_documentFile->uri().object(),
QJniObject::fromString(openModeStr).object<jstring>());
@ -373,7 +370,7 @@ public:
{
auto cursor = contentResolverInstance().callMethod<QtJniTypes::CursorType>(
"query",
uri.object<QtJniTypes::UriType>(),
uri.object<QtJniTypes::Uri>(),
QJniArray(projection),
selection.isEmpty() ? nullptr : QJniObject::fromString(selection).object<jstring>(),
QJniArray(selectionArgs),
@ -451,7 +448,7 @@ const QLatin1String MIME_TYPE_DIR("vnd.android.document/directory");
QString documentId(const QJniObject &uri)
{
return QJniObject::callStaticMethod<jstring, QtJniTypes::UriType>(
return QJniObject::callStaticMethod<jstring, QtJniTypes::Uri>(
QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(),
"getDocumentId",
uri.object()).toString();
@ -459,7 +456,7 @@ QString documentId(const QJniObject &uri)
QString treeDocumentId(const QJniObject &uri)
{
return QJniObject::callStaticMethod<jstring, QtJniTypes::UriType>(
return QJniObject::callStaticMethod<jstring, QtJniTypes::Uri>(
QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(),
"getTreeDocumentId",
uri.object()).toString();
@ -467,20 +464,20 @@ QString treeDocumentId(const QJniObject &uri)
QJniObject buildChildDocumentsUriUsingTree(const QJniObject &uri, const QString &parentDocumentId)
{
return QJniObject::callStaticMethod<QtJniTypes::UriType>(
return QJniObject::callStaticMethod<QtJniTypes::Uri>(
QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(),
"buildChildDocumentsUriUsingTree",
uri.object<QtJniTypes::UriType>(),
uri.object<QtJniTypes::Uri>(),
QJniObject::fromString(parentDocumentId).object<jstring>());
}
QJniObject buildDocumentUriUsingTree(const QJniObject &treeUri, const QString &documentId)
{
return QJniObject::callStaticMethod<QtJniTypes::UriType>(
return QJniObject::callStaticMethod<QtJniTypes::Uri>(
QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(),
"buildDocumentUriUsingTree",
treeUri.object<QtJniTypes::UriType>(),
treeUri.object<QtJniTypes::Uri>(),
QJniObject::fromString(documentId).object<jstring>());
}
@ -490,7 +487,7 @@ bool isDocumentUri(const QJniObject &uri)
QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(),
"isDocumentUri",
QNativeInterface::QAndroidApplication::context(),
uri.object<QtJniTypes::UriType>());
uri.object<QtJniTypes::Uri>());
}
bool isTreeUri(const QJniObject &uri)
@ -498,17 +495,17 @@ bool isTreeUri(const QJniObject &uri)
return QJniObject::callStaticMethod<jboolean>(
QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(),
"isTreeUri",
uri.object<QtJniTypes::UriType>());
uri.object<QtJniTypes::Uri>());
}
QJniObject createDocument(const QJniObject &parentDocumentUri, const QString &mimeType,
const QString &displayName)
{
return QJniObject::callStaticMethod<QtJniTypes::UriType>(
return QJniObject::callStaticMethod<QtJniTypes::Uri>(
QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(),
"createDocument",
contentResolverInstance().object<QtJniTypes::ContentResolverType>(),
parentDocumentUri.object<QtJniTypes::UriType>(),
contentResolverInstance().object<QtJniTypes::ContentResolver>(),
parentDocumentUri.object<QtJniTypes::Uri>(),
QJniObject::fromString(mimeType).object<jstring>(),
QJniObject::fromString(displayName).object<jstring>());
}
@ -522,8 +519,8 @@ bool deleteDocument(const QJniObject &documentUri)
return QJniObject::callStaticMethod<jboolean>(
QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(),
"deleteDocument",
contentResolverInstance().object<QtJniTypes::ContentResolverType>(),
documentUri.object<QtJniTypes::UriType>());
contentResolverInstance().object<QtJniTypes::ContentResolver>(),
documentUri.object<QtJniTypes::Uri>());
}
QJniObject moveDocument(const QJniObject &sourceDocumentUri,
@ -534,13 +531,13 @@ QJniObject moveDocument(const QJniObject &sourceDocumentUri,
if (!(flags & Document::FLAG_SUPPORTS_MOVE))
return {};
return QJniObject::callStaticMethod<QtJniTypes::UriType>(
return QJniObject::callStaticMethod<QtJniTypes::Uri>(
QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(),
"moveDocument",
contentResolverInstance().object<QtJniTypes::ContentResolverType>(),
sourceDocumentUri.object<QtJniTypes::UriType>(),
sourceParentDocumentUri.object<QtJniTypes::UriType>(),
targetParentDocumentUri.object<QtJniTypes::UriType>());
contentResolverInstance().object<QtJniTypes::ContentResolver>(),
sourceDocumentUri.object<QtJniTypes::Uri>(),
sourceParentDocumentUri.object<QtJniTypes::Uri>(),
targetParentDocumentUri.object<QtJniTypes::Uri>());
}
QJniObject renameDocument(const QJniObject &documentUri, const QString &displayName)
@ -549,11 +546,11 @@ QJniObject renameDocument(const QJniObject &documentUri, const QString &displayN
if (!(flags & Document::FLAG_SUPPORTS_RENAME))
return {};
return QJniObject::callStaticMethod<QtJniTypes::UriType>(
return QJniObject::callStaticMethod<QtJniTypes::Uri>(
QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(),
"renameDocument",
contentResolverInstance().object<QtJniTypes::ContentResolverType>(),
documentUri.object<QtJniTypes::UriType>(),
contentResolverInstance().object<QtJniTypes::ContentResolver>(),
documentUri.object<QtJniTypes::Uri>(),
QJniObject::fromString(displayName).object<jstring>());
}
} // End DocumentsContract namespace
@ -584,7 +581,7 @@ QJniObject parseUri(const QString &uri)
if (uriToParse.contains(' '))
uriToParse.replace(' ', QUrl::toPercentEncoding(" "));
return QJniObject::callStaticMethod<QtJniTypes::UriType>(
return QJniObject::callStaticMethod<QtJniTypes::Uri>(
QtJniTypes::Traits<QtJniTypes::Uri>::className(),
"parse",
QJniObject::fromString(uriToParse).object<jstring>());
@ -721,7 +718,7 @@ bool DocumentFile::canRead() const
{
const auto context = QJniObject(QNativeInterface::QAndroidApplication::context());
const bool selfUriPermission = context.callMethod<jint>("checkCallingOrSelfUriPermission",
m_uri.object<QtJniTypes::UriType>(),
m_uri.object<QtJniTypes::Uri>(),
FLAG_GRANT_READ_URI_PERMISSION);
if (selfUriPermission != 0)
return false;
@ -733,7 +730,7 @@ bool DocumentFile::canWrite() const
{
const auto context = QJniObject(QNativeInterface::QAndroidApplication::context());
const bool selfUriPermission = context.callMethod<jint>("checkCallingOrSelfUriPermission",
m_uri.object<QtJniTypes::UriType>(),
m_uri.object<QtJniTypes::Uri>(),
FLAG_GRANT_WRITE_URI_PERMISSION);
if (selfUriPermission != 0)
return false;

View File

@ -28,12 +28,9 @@ Q_DECLARE_JNI_CLASS(FontInfo, "androidx/core/provider/FontsContractCompat$FontIn
// various utility types
Q_DECLARE_JNI_CLASS(List, "java/util/List"); // List is just an Interface
Q_DECLARE_JNI_CLASS(ArrayList, "java/util/ArrayList");
Q_DECLARE_JNI_CLASS(HashSet, "java/util/HashSet");
Q_DECLARE_JNI_CLASS(Uri, "android/net/Uri")
Q_DECLARE_JNI_CLASS(CancellationSignal, "android/os/CancellationSignal")
Q_DECLARE_JNI_CLASS(ParcelFileDescriptor, "android/os/ParcelFileDescriptor")
Q_DECLARE_JNI_CLASS(ContentResolver, "android/content/ContentResolver")
Q_DECLARE_JNI_CLASS(PackageManager, "android/content/pm/PackageManager")
Q_DECLARE_JNI_CLASS(ProviderInfo, "android/content/pm/ProviderInfo")
Q_DECLARE_JNI_CLASS(PackageInfo, "android/content/pm/PackageInfo")

View File

@ -38,9 +38,6 @@ QAndroidPlatformServices::QAndroidPlatformServices()
}
}
Q_DECLARE_JNI_CLASS(UriType, "android/net/Uri")
Q_DECLARE_JNI_CLASS(FileType, "java/io/File")
Q_DECLARE_JNI_CLASS(File, "java/io/File")
Q_DECLARE_JNI_CLASS(FileProvider, "androidx/core/content/FileProvider");
bool QAndroidPlatformServices::openUrl(const QUrl &theUrl)
@ -84,10 +81,10 @@ bool QAndroidPlatformServices::openUrl(const QUrl &theUrl)
const auto urlFile = QJniObject(QtJniTypes::Traits<QtJniTypes::File>::className(),
urlPath.object<jstring>());
const auto fileProviderUri = QJniObject::callStaticMethod<QtJniTypes::UriType>(
const auto fileProviderUri = QJniObject::callStaticMethod<QtJniTypes::Uri>(
QtJniTypes::Traits<QtJniTypes::FileProvider>::className(), "getUriForFile",
QAndroidApplication::context(), providerName.object<jstring>(),
urlFile.object<QtJniTypes::FileType>());
urlFile.object<QtJniTypes::File>());
if (fileProviderUri.isValid())
return openUrl(fileProviderUri.callMethod<jstring>("toString"));

View File

@ -63,7 +63,6 @@ Q_DECLARE_JNI_CLASS(JavaType, "org/qtproject/qt/JavaType");
static_assert(QtJniTypes::Traits<QtJniTypes::JavaType>::signature() == "Lorg/qtproject/qt/JavaType;");
static_assert(QtJniTypes::Traits<QtJniTypes::JavaType[]>::signature() == "[Lorg/qtproject/qt/JavaType;");
Q_DECLARE_JNI_CLASS(String, "java/lang/String");
static_assert(QtJniTypes::Traits<jstring>::className() == "java/lang/String");
static_assert(QtJniTypes::Traits<QtJniTypes::String>::className() == "java/lang/String");
static_assert(QtJniTypes::Traits<QtJniTypes::String>::signature() == "Ljava/lang/String;");