diff options
Diffstat (limited to 'src/plugins/platforms/android/androidcontentfileengine.cpp')
-rw-r--r-- | src/plugins/platforms/android/androidcontentfileengine.cpp | 165 |
1 files changed, 75 insertions, 90 deletions
diff --git a/src/plugins/platforms/android/androidcontentfileengine.cpp b/src/plugins/platforms/android/androidcontentfileengine.cpp index c86bbeae77..f4afb3789a 100644 --- a/src/plugins/platforms/android/androidcontentfileengine.cpp +++ b/src/plugins/platforms/android/androidcontentfileengine.cpp @@ -16,19 +16,15 @@ QT_BEGIN_NAMESPACE using namespace QNativeInterface; 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;"); +Q_DECLARE_JNI_CLASS(ParcelFileDescriptorType, "android/os/ParcelFileDescriptor"); +Q_DECLARE_JNI_CLASS(CursorType, "android/database/Cursor"); static QJniObject &contentResolverInstance() { static QJniObject contentResolver; if (!contentResolver.isValid()) { contentResolver = QJniObject(QNativeInterface::QAndroidApplication::context()) - .callMethod<QtJniTypes::ContentResolverType>("getContentResolver"); + .callMethod<QtJniTypes::ContentResolver>("getContentResolver"); } return contentResolver; @@ -80,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>()); @@ -194,10 +190,10 @@ QByteArray AndroidContentFileEngine::id() const return m_documentFile->id().toUtf8(); } -QDateTime AndroidContentFileEngine::fileTime(FileTime time) const +QDateTime AndroidContentFileEngine::fileTime(QFile::FileTime time) const { switch (time) { - case FileTime::ModificationTime: + case QFile::FileModificationTime: return m_documentFile->lastModified(); break; default: @@ -248,47 +244,37 @@ QString AndroidContentFileEngine::fileName(FileName f) const return QString(); } -QAbstractFileEngine::Iterator *AndroidContentFileEngine::beginEntryList(QDir::Filters filters, - const QStringList &filterNames) +QAbstractFileEngine::IteratorUniquePtr +AndroidContentFileEngine::beginEntryList(const QString &path, QDir::Filters filters, + const QStringList &filterNames) { - return new AndroidContentFileEngineIterator(filters, filterNames); -} - -QAbstractFileEngine::Iterator *AndroidContentFileEngine::endEntryList() -{ - return nullptr; + return std::make_unique<AndroidContentFileEngineIterator>(path, filters, filterNames); } AndroidContentFileEngineHandler::AndroidContentFileEngineHandler() = default; AndroidContentFileEngineHandler::~AndroidContentFileEngineHandler() = default; -QAbstractFileEngine* AndroidContentFileEngineHandler::create(const QString &fileName) const +std::unique_ptr<QAbstractFileEngine> +AndroidContentFileEngineHandler::create(const QString &fileName) const { - if (!fileName.startsWith("content"_L1)) - return nullptr; + if (fileName.startsWith("content"_L1)) + return std::make_unique<AndroidContentFileEngine>(fileName); - return new AndroidContentFileEngine(fileName); -} + return {}; -AndroidContentFileEngineIterator::AndroidContentFileEngineIterator(QDir::Filters filters, - const QStringList &filterNames) - : QAbstractFileEngineIterator(filters, filterNames) -{ } -AndroidContentFileEngineIterator::~AndroidContentFileEngineIterator() +AndroidContentFileEngineIterator::AndroidContentFileEngineIterator( + const QString &path, QDir::Filters filters, const QStringList &filterNames) + : QAbstractFileEngineIterator(path, filters, filterNames) { } -QString AndroidContentFileEngineIterator::next() +AndroidContentFileEngineIterator::~AndroidContentFileEngineIterator() { - if (!hasNext()) - return QString(); - ++m_index; - return currentFilePath(); } -bool AndroidContentFileEngineIterator::hasNext() const +bool AndroidContentFileEngineIterator::advance() { if (m_index == -1 && m_files.isEmpty()) { const auto currentPath = path(); @@ -299,9 +285,18 @@ bool AndroidContentFileEngineIterator::hasNext() const if (iterDoc->isDirectory()) for (const auto &doc : iterDoc->listFiles()) m_files.append(doc); + if (m_files.isEmpty()) + return false; + m_index = 0; + return true; + } + + if (m_index < m_files.size() - 1) { + ++m_index; + return true; } - return m_index < (m_files.size() - 1); + return false; } QString AndroidContentFileEngineIterator::currentFileName() const @@ -375,12 +370,10 @@ public: { auto cursor = contentResolverInstance().callMethod<QtJniTypes::CursorType>( "query", - uri.object<QtJniTypes::UriType>(), - projection.isEmpty() ? - nullptr : fromStringList(projection).object<QtJniTypes::StringArray>(), + uri.object<QtJniTypes::Uri>(), + QJniArray(projection), selection.isEmpty() ? nullptr : QJniObject::fromString(selection).object<jstring>(), - selectionArgs.isEmpty() ? - nullptr : fromStringList(selectionArgs).object<QtJniTypes::StringArray>(), + QJniArray(selectionArgs), sortOrder.isEmpty() ? nullptr : QJniObject::fromString(sortOrder).object<jstring>()); if (!cursor.isValid()) return {}; @@ -414,15 +407,6 @@ public: bool moveToNext() { return m_object.callMethod<jboolean>("moveToNext"); } private: - static QJniObject fromStringList(const QStringList &list) - { - QJniEnvironment env; - auto array = env->NewObjectArray(list.size(), env.findClass("java/lang/String"), nullptr); - for (int i = 0; i < list.size(); ++i) - env->SetObjectArrayElement(array, i, QJniObject::fromString(list[i]).object()); - return QJniObject::fromLocalRef(array); - } - QJniObject m_object; }; @@ -464,64 +448,64 @@ const QLatin1String MIME_TYPE_DIR("vnd.android.document/directory"); QString documentId(const QJniObject &uri) { - return QJniObject::callStaticMethod<jstring, QtJniTypes::UriType>( - QtJniTypes::className<QtJniTypes::DocumentsContract>(), + return QJniObject::callStaticMethod<jstring, QtJniTypes::Uri>( + QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(), "getDocumentId", uri.object()).toString(); } QString treeDocumentId(const QJniObject &uri) { - return QJniObject::callStaticMethod<jstring, QtJniTypes::UriType>( - QtJniTypes::className<QtJniTypes::DocumentsContract>(), + return QJniObject::callStaticMethod<jstring, QtJniTypes::Uri>( + QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(), "getTreeDocumentId", uri.object()).toString(); } QJniObject buildChildDocumentsUriUsingTree(const QJniObject &uri, const QString &parentDocumentId) { - return QJniObject::callStaticMethod<QtJniTypes::UriType>( - QtJniTypes::className<QtJniTypes::DocumentsContract>(), + 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>( - QtJniTypes::className<QtJniTypes::DocumentsContract>(), + return QJniObject::callStaticMethod<QtJniTypes::Uri>( + QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(), "buildDocumentUriUsingTree", - treeUri.object<QtJniTypes::UriType>(), + treeUri.object<QtJniTypes::Uri>(), QJniObject::fromString(documentId).object<jstring>()); } bool isDocumentUri(const QJniObject &uri) { return QJniObject::callStaticMethod<jboolean>( - QtJniTypes::className<QtJniTypes::DocumentsContract>(), + QtJniTypes::Traits<QtJniTypes::DocumentsContract>::className(), "isDocumentUri", QNativeInterface::QAndroidApplication::context(), - uri.object<QtJniTypes::UriType>()); + uri.object<QtJniTypes::Uri>()); } bool isTreeUri(const QJniObject &uri) { return QJniObject::callStaticMethod<jboolean>( - QtJniTypes::className<QtJniTypes::DocumentsContract>(), + 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>( - QtJniTypes::className<QtJniTypes::DocumentsContract>(), + 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>()); } @@ -533,10 +517,10 @@ bool deleteDocument(const QJniObject &documentUri) return {}; return QJniObject::callStaticMethod<jboolean>( - QtJniTypes::className<QtJniTypes::DocumentsContract>(), + 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, @@ -547,13 +531,13 @@ QJniObject moveDocument(const QJniObject &sourceDocumentUri, if (!(flags & Document::FLAG_SUPPORTS_MOVE)) return {}; - return QJniObject::callStaticMethod<QtJniTypes::UriType>( - QtJniTypes::className<QtJniTypes::DocumentsContract>(), + 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) @@ -562,11 +546,11 @@ QJniObject renameDocument(const QJniObject &documentUri, const QString &displayN if (!(flags & Document::FLAG_SUPPORTS_RENAME)) return {}; - return QJniObject::callStaticMethod<QtJniTypes::UriType>( - QtJniTypes::className<QtJniTypes::DocumentsContract>(), + 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 @@ -597,33 +581,34 @@ QJniObject parseUri(const QString &uri) if (uriToParse.contains(' ')) uriToParse.replace(' ', QUrl::toPercentEncoding(" ")); - return QJniObject::callStaticMethod<QtJniTypes::UriType>( - QtJniTypes::className<QtJniTypes::Uri>(), + return QJniObject::callStaticMethod<QtJniTypes::Uri>( + QtJniTypes::Traits<QtJniTypes::Uri>::className(), "parse", QJniObject::fromString(uriToParse).object<jstring>()); } DocumentFilePtr DocumentFile::parseFromAnyUri(const QString &fileName) { - const QJniObject uri = parseUri(fileName); + const QString encodedUri = QUrl(fileName).toEncoded(); + const QJniObject uri = parseUri(encodedUri); - if (DocumentsContract::isDocumentUri(uri)) + if (DocumentsContract::isDocumentUri(uri) || !DocumentsContract::isTreeUri(uri)) return fromSingleUri(uri); const QString documentType = "/document/"_L1; const QString treeType = "/tree/"_L1; - const int treeIndex = fileName.indexOf(treeType); - const int documentIndex = fileName.indexOf(documentType); + const int treeIndex = encodedUri.indexOf(treeType); + const int documentIndex = encodedUri.indexOf(documentType); const int index = fileName.lastIndexOf("/"); if (index <= treeIndex + treeType.size() || index <= documentIndex + documentType.size()) return fromTreeUri(uri); - const QString parentUrl = fileName.left(index); + const QString parentUrl = encodedUri.left(index); DocumentFilePtr parentDocFile = fromTreeUri(parseUri(parentUrl)); - const QString baseName = fileName.mid(index); + const QString baseName = encodedUri.mid(index); const QString fileUrl = parentUrl + QUrl::toPercentEncoding(baseName); DocumentFilePtr docFile = std::make_shared<MakeableDocumentFile>(parseUri(fileUrl)); @@ -733,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; @@ -745,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; |