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:
parent
7fe2537ce2
commit
ba3db0cacd
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user