Android: use signature-less jni syntax for AndroidContentFileEngine

Task-number: QTBUG-98974
Pick-to: 6.5 6.4
Change-Id: I1e8e102282af2877bbbe6e8018b7649fac66804e
Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
This commit is contained in:
Assam Boudjelthia 2022-12-30 15:02:07 +02:00
parent 7fe2537ce2
commit ba3db0cacd

View File

@ -14,12 +14,19 @@
using namespace QNativeInterface; using namespace QNativeInterface;
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
Q_DECLARE_JNI_TYPE(ContentResolverType, "Landroid/content/ContentResolver;");
Q_DECLARE_JNI_TYPE(UriType, "Landroid/net/Uri;");
Q_DECLARE_JNI_CLASS(Uri, "android/net/Uri");
Q_DECLARE_JNI_TYPE(ParcelFileDescriptorType, "Landroid/os/ParcelFileDescriptor;");
Q_DECLARE_JNI_TYPE(CursorType, "Landroid/database/Cursor;");
Q_DECLARE_JNI_TYPE(StringArray, "[Ljava/lang/String;");
static QJniObject &contentResolverInstance() static QJniObject &contentResolverInstance()
{ {
static QJniObject contentResolver; static QJniObject contentResolver;
if (!contentResolver.isValid()) { if (!contentResolver.isValid()) {
contentResolver = QJniObject(QNativeInterface::QAndroidApplication::context()) contentResolver = QJniObject(QNativeInterface::QAndroidApplication::context())
.callObjectMethod("getContentResolver", "()Landroid/content/ContentResolver;"); .callMethod<QtJniTypes::ContentResolverType>("getContentResolver");
} }
return contentResolver; return contentResolver;
@ -70,15 +77,16 @@ bool AndroidContentFileEngine::open(QIODevice::OpenMode openMode,
openModeStr += u'a'; openModeStr += u'a';
} }
m_pfd = contentResolverInstance().callObjectMethod("openFileDescriptor", m_pfd = contentResolverInstance().callMethod<
"(Landroid/net/Uri;Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;", QtJniTypes::ParcelFileDescriptorType, QtJniTypes::UriType, jstring>(
"openFileDescriptor",
m_documentFile->uri().object(), m_documentFile->uri().object(),
QJniObject::fromString(openModeStr).object()); QJniObject::fromString(openModeStr).object<jstring>());
if (!m_pfd.isValid()) if (!m_pfd.isValid())
return false; return false;
const auto fd = m_pfd.callMethod<jint>("getFd", "()I"); const auto fd = m_pfd.callMethod<jint>("getFd");
if (fd < 0) { if (fd < 0) {
closeNativeFileDescriptor(); closeNativeFileDescriptor();
@ -97,7 +105,7 @@ bool AndroidContentFileEngine::close()
void AndroidContentFileEngine::closeNativeFileDescriptor() void AndroidContentFileEngine::closeNativeFileDescriptor()
{ {
if (m_pfd.isValid()) { if (m_pfd.isValid()) {
m_pfd.callMethod<void>("close", "()V"); m_pfd.callMethod<void>("close");
m_pfd = QJniObject(); m_pfd = QJniObject();
} }
} }
@ -332,21 +340,19 @@ public:
QVariant data(int columnIndex) const QVariant data(int columnIndex) const
{ {
int type = m_object.callMethod<jint>("getType", "(I)I", columnIndex); int type = m_object.callMethod<jint>("getType", columnIndex);
switch (type) { switch (type) {
case FIELD_TYPE_NULL: case FIELD_TYPE_NULL:
return {}; return {};
case FIELD_TYPE_INTEGER: case FIELD_TYPE_INTEGER:
return QVariant::fromValue(m_object.callMethod<jlong>("getLong", "(I)J", columnIndex)); return QVariant::fromValue(m_object.callMethod<jlong>("getLong", columnIndex));
case FIELD_TYPE_FLOAT: case FIELD_TYPE_FLOAT:
return QVariant::fromValue(m_object.callMethod<jdouble>("getDouble", "(I)D", return QVariant::fromValue(m_object.callMethod<jdouble>("getDouble", columnIndex));
columnIndex));
case FIELD_TYPE_STRING: case FIELD_TYPE_STRING:
return QVariant::fromValue(m_object.callObjectMethod("getString", return QVariant::fromValue(m_object.callMethod<jstring>("getString",
"(I)Ljava/lang/String;",
columnIndex).toString()); columnIndex).toString());
case FIELD_TYPE_BLOB: { case FIELD_TYPE_BLOB: {
auto blob = m_object.callObjectMethod("getBlob", "(I)[B", columnIndex); auto blob = m_object.callMethod<jbyteArray>("getBlob", columnIndex);
QJniEnvironment env; QJniEnvironment env;
const auto blobArray = blob.object<jbyteArray>(); const auto blobArray = blob.object<jbyteArray>();
const int size = env->GetArrayLength(blobArray); const int size = env->GetArrayLength(blobArray);
@ -365,13 +371,15 @@ public:
const QStringList &selectionArgs = {}, const QStringList &selectionArgs = {},
const QString &sortOrder = {}) const QString &sortOrder = {})
{ {
auto cursor = contentResolverInstance().callObjectMethod("query", auto cursor = contentResolverInstance().callMethod<QtJniTypes::CursorType>(
"(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;", "query",
uri.object(), uri.object<QtJniTypes::UriType>(),
projection.isEmpty() ? nullptr : fromStringList(projection).object(), projection.isEmpty() ?
selection.isEmpty() ? nullptr : QJniObject::fromString(selection).object(), nullptr : fromStringList(projection).object<QtJniTypes::StringArray>(),
selectionArgs.isEmpty() ? nullptr : fromStringList(selectionArgs).object(), selection.isEmpty() ? nullptr : QJniObject::fromString(selection).object<jstring>(),
sortOrder.isEmpty() ? nullptr : QJniObject::fromString(sortOrder).object()); selectionArgs.isEmpty() ?
nullptr : fromStringList(selectionArgs).object<QtJniTypes::StringArray>(),
sortOrder.isEmpty() ? nullptr : QJniObject::fromString(sortOrder).object<jstring>());
if (!cursor.isValid()) if (!cursor.isValid())
return {}; return {};
return std::make_unique<Cursor>(cursor); return std::make_unique<Cursor>(cursor);
@ -391,7 +399,7 @@ public:
bool isNull(int columnIndex) const bool isNull(int columnIndex) const
{ {
return m_object.callMethod<jboolean>("isNull", "(I)Z", columnIndex); return m_object.callMethod<jboolean>("isNull", columnIndex);
} }
int columnCount() const { return m_object.callMethod<jint>("getColumnCount"); } int columnCount() const { return m_object.callMethod<jint>("getColumnCount"); }
@ -407,7 +415,7 @@ private:
static QJniObject fromStringList(const QStringList &list) static QJniObject fromStringList(const QStringList &list)
{ {
QJniEnvironment env; QJniEnvironment env;
auto array = env->NewObjectArray(list.size(), env->FindClass("java/lang/String"), nullptr); auto array = env->NewObjectArray(list.size(), env.findClass("java/lang/String"), nullptr);
for (int i = 0; i < list.size(); ++i) for (int i = 0; i < list.size(); ++i)
env->SetObjectArrayElement(array, i, QJniObject::fromString(list[i]).object()); env->SetObjectArrayElement(array, i, QJniObject::fromString(list[i]).object());
return QJniObject::fromLocalRef(array); return QJniObject::fromLocalRef(array);
@ -420,6 +428,8 @@ private:
// Start of DocumentsContract // Start of DocumentsContract
Q_DECLARE_JNI_CLASS(DocumentsContract, "android/provider/DocumentsContract");
/*! /*!
* *
* DocumentsContract Api. * DocumentsContract Api.
@ -452,66 +462,66 @@ const QLatin1String MIME_TYPE_DIR("vnd.android.document/directory");
QString documentId(const QJniObject &uri) QString documentId(const QJniObject &uri)
{ {
return QJniObject::callStaticObjectMethod("android/provider/DocumentsContract", return QJniObject::callStaticMethod<jstring, QtJniTypes::UriType>(
QtJniTypes::className<QtJniTypes::DocumentsContract>(),
"getDocumentId", "getDocumentId",
"(Landroid/net/Uri;)Ljava/lang/String;",
uri.object()).toString(); uri.object()).toString();
} }
QString treeDocumentId(const QJniObject &uri) QString treeDocumentId(const QJniObject &uri)
{ {
return QJniObject::callStaticObjectMethod("android/provider/DocumentsContract", return QJniObject::callStaticMethod<jstring, QtJniTypes::UriType>(
QtJniTypes::className<QtJniTypes::DocumentsContract>(),
"getTreeDocumentId", "getTreeDocumentId",
"(Landroid/net/Uri;)Ljava/lang/String;",
uri.object()).toString(); uri.object()).toString();
} }
QJniObject buildChildDocumentsUriUsingTree(const QJniObject &uri, const QString &parentDocumentId) QJniObject buildChildDocumentsUriUsingTree(const QJniObject &uri, const QString &parentDocumentId)
{ {
return QJniObject::callStaticObjectMethod("android/provider/DocumentsContract", return QJniObject::callStaticMethod<QtJniTypes::UriType>(
QtJniTypes::className<QtJniTypes::DocumentsContract>(),
"buildChildDocumentsUriUsingTree", "buildChildDocumentsUriUsingTree",
"(Landroid/net/Uri;Ljava/lang/String;)Landroid/net/Uri;", uri.object<QtJniTypes::UriType>(),
uri.object(), QJniObject::fromString(parentDocumentId).object<jstring>());
QJniObject::fromString(parentDocumentId).object());
} }
QJniObject buildDocumentUriUsingTree(const QJniObject &treeUri, const QString &documentId) QJniObject buildDocumentUriUsingTree(const QJniObject &treeUri, const QString &documentId)
{ {
return QJniObject::callStaticObjectMethod("android/provider/DocumentsContract", return QJniObject::callStaticMethod<QtJniTypes::UriType>(
QtJniTypes::className<QtJniTypes::DocumentsContract>(),
"buildDocumentUriUsingTree", "buildDocumentUriUsingTree",
"(Landroid/net/Uri;Ljava/lang/String;)Landroid/net/Uri;", treeUri.object<QtJniTypes::UriType>(),
treeUri.object(), QJniObject::fromString(documentId).object<jstring>());
QJniObject::fromString(documentId).object());
} }
bool isDocumentUri(const QJniObject &uri) bool isDocumentUri(const QJniObject &uri)
{ {
return QJniObject::callStaticMethod<jboolean>("android/provider/DocumentsContract", return QJniObject::callStaticMethod<jboolean>(
QtJniTypes::className<QtJniTypes::DocumentsContract>(),
"isDocumentUri", "isDocumentUri",
"(Landroid/content/Context;Landroid/net/Uri;)Z",
QNativeInterface::QAndroidApplication::context(), QNativeInterface::QAndroidApplication::context(),
uri.object()); uri.object<QtJniTypes::UriType>());
} }
bool isTreeUri(const QJniObject &uri) bool isTreeUri(const QJniObject &uri)
{ {
return QJniObject::callStaticMethod<jboolean>("android/provider/DocumentsContract", return QJniObject::callStaticMethod<jboolean>(
QtJniTypes::className<QtJniTypes::DocumentsContract>(),
"isTreeUri", "isTreeUri",
"(Landroid/net/Uri;)Z", uri.object<QtJniTypes::UriType>());
uri.object());
} }
QJniObject createDocument(const QJniObject &parentDocumentUri, const QString &mimeType, QJniObject createDocument(const QJniObject &parentDocumentUri, const QString &mimeType,
const QString &displayName) const QString &displayName)
{ {
return QJniObject::callStaticObjectMethod("android/provider/DocumentsContract", return QJniObject::callStaticMethod<QtJniTypes::UriType>(
QtJniTypes::className<QtJniTypes::DocumentsContract>(),
"createDocument", "createDocument",
"(Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri;", contentResolverInstance().object<QtJniTypes::ContentResolverType>(),
contentResolverInstance().object(), parentDocumentUri.object<QtJniTypes::UriType>(),
parentDocumentUri.object(), QJniObject::fromString(mimeType).object<jstring>(),
QJniObject::fromString(mimeType).object(), QJniObject::fromString(displayName).object<jstring>());
QJniObject::fromString(displayName).object());
} }
bool deleteDocument(const QJniObject &documentUri) bool deleteDocument(const QJniObject &documentUri)
@ -520,11 +530,11 @@ bool deleteDocument(const QJniObject &documentUri)
if (!(flags & Document::FLAG_SUPPORTS_DELETE)) if (!(flags & Document::FLAG_SUPPORTS_DELETE))
return {}; return {};
return QJniObject::callStaticMethod<jboolean>("android/provider/DocumentsContract", return QJniObject::callStaticMethod<jboolean>(
QtJniTypes::className<QtJniTypes::DocumentsContract>(),
"deleteDocument", "deleteDocument",
"(Landroid/content/ContentResolver;Landroid/net/Uri;)Z", contentResolverInstance().object<QtJniTypes::ContentResolverType>(),
contentResolverInstance().object(), documentUri.object<QtJniTypes::UriType>());
documentUri.object());
} }
QJniObject moveDocument(const QJniObject &sourceDocumentUri, QJniObject moveDocument(const QJniObject &sourceDocumentUri,
@ -535,13 +545,13 @@ QJniObject moveDocument(const QJniObject &sourceDocumentUri,
if (!(flags & Document::FLAG_SUPPORTS_MOVE)) if (!(flags & Document::FLAG_SUPPORTS_MOVE))
return {}; return {};
return QJniObject::callStaticObjectMethod("android/provider/DocumentsContract", return QJniObject::callStaticMethod<QtJniTypes::UriType>(
QtJniTypes::className<QtJniTypes::DocumentsContract>(),
"moveDocument", "moveDocument",
"(Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/net/Uri;Landroid/net/Uri;)Landroid/net/Uri;", contentResolverInstance().object<QtJniTypes::ContentResolverType>(),
contentResolverInstance().object(), sourceDocumentUri.object<QtJniTypes::UriType>(),
sourceDocumentUri.object(), sourceParentDocumentUri.object<QtJniTypes::UriType>(),
sourceParentDocumentUri.object(), targetParentDocumentUri.object<QtJniTypes::UriType>());
targetParentDocumentUri.object());
} }
QJniObject renameDocument(const QJniObject &documentUri, const QString &displayName) QJniObject renameDocument(const QJniObject &documentUri, const QString &displayName)
@ -550,12 +560,12 @@ QJniObject renameDocument(const QJniObject &documentUri, const QString &displayN
if (!(flags & Document::FLAG_SUPPORTS_RENAME)) if (!(flags & Document::FLAG_SUPPORTS_RENAME))
return {}; return {};
return QJniObject::callStaticObjectMethod("android/provider/DocumentsContract", return QJniObject::callStaticMethod<QtJniTypes::UriType>(
QtJniTypes::className<QtJniTypes::DocumentsContract>(),
"renameDocument", "renameDocument",
"(Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;)Landroid/net/Uri;", contentResolverInstance().object<QtJniTypes::ContentResolverType>(),
contentResolverInstance().object(), documentUri.object<QtJniTypes::UriType>(),
documentUri.object(), QJniObject::fromString(displayName).object<jstring>());
QJniObject::fromString(displayName).object());
} }
} // End DocumentsContract namespace } // End DocumentsContract namespace
@ -581,10 +591,10 @@ DocumentFile::DocumentFile(const QJniObject &uri,
QJniObject parseUri(const QString &uri) QJniObject parseUri(const QString &uri)
{ {
return QJniObject::callStaticObjectMethod("android/net/Uri", return QJniObject::callStaticMethod<QtJniTypes::UriType>(
QtJniTypes::className<QtJniTypes::Uri>(),
"parse", "parse",
"(Ljava/lang/String;)Landroid/net/Uri;", QJniObject::fromString(uri).object<jstring>());
QJniObject::fromString(uri).object());
} }
DocumentFilePtr DocumentFile::parseFromAnyUri(const QString &fileName) DocumentFilePtr DocumentFile::parseFromAnyUri(const QString &fileName)
@ -717,8 +727,7 @@ bool DocumentFile::canRead() const
{ {
const auto context = QJniObject(QNativeInterface::QAndroidApplication::context()); const auto context = QJniObject(QNativeInterface::QAndroidApplication::context());
const bool selfUriPermission = context.callMethod<jint>("checkCallingOrSelfUriPermission", const bool selfUriPermission = context.callMethod<jint>("checkCallingOrSelfUriPermission",
"(Landroid/net/Uri;I)I", m_uri.object<QtJniTypes::UriType>(),
m_uri.object(),
FLAG_GRANT_READ_URI_PERMISSION); FLAG_GRANT_READ_URI_PERMISSION);
if (selfUriPermission != 0) if (selfUriPermission != 0)
return false; return false;
@ -730,8 +739,7 @@ bool DocumentFile::canWrite() const
{ {
const auto context = QJniObject(QNativeInterface::QAndroidApplication::context()); const auto context = QJniObject(QNativeInterface::QAndroidApplication::context());
const bool selfUriPermission = context.callMethod<jint>("checkCallingOrSelfUriPermission", const bool selfUriPermission = context.callMethod<jint>("checkCallingOrSelfUriPermission",
"(Landroid/net/Uri;I)I", m_uri.object<QtJniTypes::UriType>(),
m_uri.object(),
FLAG_GRANT_WRITE_URI_PERMISSION); FLAG_GRANT_WRITE_URI_PERMISSION);
if (selfUriPermission != 0) if (selfUriPermission != 0)
return false; return false;