Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 46 additions & 3 deletions shared_storage/sharedstorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const QLatin1String ACTION_OPEN_DOCUMENT("android.intent.action.OPEN_DOCUMENT");
const QLatin1String ACTION_OPEN_DOCUMENT_TREE("android.intent.action.OPEN_DOCUMENT_TREE");
const QLatin1String CATEGORY_OPENABLE("android.intent.category.OPENABLE");
const QLatin1String EXTRA_MIME_TYPES("android.intent.extra.MIME_TYPES");
const QLatin1String EXTRA_ALLOW_MULTIPLE("android.intent.extra.ALLOW_MULTIPLE");
const QLatin1String EXTRA_TITLE("android.intent.extra.TITLE");

constexpr int RESULT_OK = 0xffffffff;
Expand All @@ -37,7 +38,7 @@ QJniObject createDocument(const QString &mimeType, const QString &title, const Q
return intent;
}

QJniObject openDocument(const QStringList &mimeTypes, const QString &initialUri)
QJniObject openDocument(const QStringList &mimeTypes, const QString &initialUri, bool allowMultiple)
{
QJniObject intent{"android.content.Intent", "(Ljava/lang/String;)V", QJniObject::fromString(ACTION_OPEN_DOCUMENT).object()};
intent.callObjectMethod("addCategory", "(Ljava/lang/String;)Landroid/content/Intent;", QJniObject::fromString(CATEGORY_OPENABLE).object());
Expand All @@ -50,6 +51,11 @@ QJniObject openDocument(const QStringList &mimeTypes, const QString &initialUri)
QJniObject::getStaticObjectField("android/provider/DocumentsContract", "EXTRA_INITIAL_URI", "Ljava/lang/String;").object(),
QJniObject::fromString(initialUri).object());
}
if (allowMultiple) {
intent.callObjectMethod("putExtra", "(Ljava/lang/String;Z)Landroid/content/Intent;",
QJniObject::fromString(EXTRA_ALLOW_MULTIPLE).object(),
static_cast<jboolean>(true));
}
return intent;
}

Expand All @@ -64,6 +70,26 @@ QJniObject openDocumentTree(const QString &initialUri)
return intent;
}

QList<android::net::Uri> getUrisFromIntent(const QJniObject &intent) {
auto uris = QList<android::net::Uri>();
auto clipData = intent.callObjectMethod("getClipData", "()Landroid/content/ClipData;");
auto singleUri = intent.callObjectMethod("getData", "()Landroid/net/Uri;");
if (clipData.isValid()) {
// User selected multiple files
auto itemCount = clipData.callMethod<jint>("getItemCount");
for (int i = 0; i < itemCount; i++) {
auto item = clipData.callObjectMethod("getItemAt", "(I)Landroid/content/ClipData$Item;", i);
if (item.isValid()) {
auto uri = item.callObjectMethod("getUri", "()Landroid/net/Uri;");
uris.push_back(uri);
}
}
} else if (singleUri.isValid()) {
// User selected single file
uris.push_back(singleUri);
}
return uris;
}
}

namespace android {
Expand All @@ -86,13 +112,22 @@ void SharedStorage::createDocument(int requestCode, RequestResultCallback callba

void SharedStorage::openDocument(int requestCode, const RequestResultCallback &callback, const QStringList &mimeTypes, const QString &initialUri)
{
startActivity(::openDocument(mimeTypes, initialUri), requestCode,
startActivity(::openDocument(mimeTypes, initialUri, false /* allowMultiple */), requestCode,
[requestCode, callback, this](int requestId, int resultCode, QJniObject data) {
if (requestCode == requestId && resultCode == RESULT_OK)
QMetaObject::invokeMethod(this, [=]{callback(requestId, data.callObjectMethod("getData", "()Landroid/net/Uri;"));}, Qt::QueuedConnection);
});
}

void SharedStorage::openDocuments(int requestCode, const RequestMultipleResultsCallback &callback, const QStringList &mimeTypes, const QString &initialUri)
{
startActivity(::openDocument(mimeTypes, initialUri, true /* allowMultiple */), requestCode,
[requestCode, callback, this](int requestId, int resultCode, QJniObject data) {
if (requestCode == requestId && resultCode == RESULT_OK)
QMetaObject::invokeMethod(this, [=]{callback(requestId, ::getUrisFromIntent(data));}, Qt::QueuedConnection);
});
}

void SharedStorage::openDocumentTree(int requestCode, const RequestResultCallback &callback, const QString &initialUri)
{
startActivity(::openDocumentTree(initialUri), requestCode,
Expand All @@ -112,12 +147,20 @@ void SharedStorage::createDocument(int requestCode, const QString &mimeType, con

void SharedStorage::openDocument(int requestCode, const QStringList &mimeTypes, const QString &initialUri)
{
startActivity(::openDocument(mimeTypes, initialUri), requestCode, [requestCode, this](int requestId, int resultCode, QJniObject data) {
startActivity(::openDocument(mimeTypes, initialUri, false /* allowMultiple */), requestCode, [requestCode, this](int requestId, int resultCode, QJniObject data) {
if (requestCode == requestId && resultCode == RESULT_OK)
QMetaObject::invokeMethod(this, [=]{emit requestResult(requestId, data.callObjectMethod("getData", "()Landroid/net/Uri;"));});
});
}

void SharedStorage::openDocuments(int requestCode, const QStringList &mimeTypes, const QString &initialUri)
{
startActivity(::openDocument(mimeTypes, initialUri, true /* allowMultiple */), requestCode, [requestCode, this](int requestId, int resultCode, QJniObject data) {
if (requestCode == requestId && resultCode == RESULT_OK)
QMetaObject::invokeMethod(this, [=]{emit requestResults(requestId, ::getUrisFromIntent(data));});
});
}

void SharedStorage::openDocumentTree(int requestCode, const QString &initialUri)
{
startActivity(::openDocumentTree(initialUri), requestCode, [requestCode, this](int requestId, int resultCode, QJniObject data) {
Expand Down
4 changes: 4 additions & 0 deletions shared_storage/sharedstorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,22 @@ class SharedStorage : public QObject
public:
static SharedStorage &instance();
using RequestResultCallback = std::function<void(int, net::Uri)>;
using RequestMultipleResultsCallback = std::function<void(int, QList<net::Uri>)>;

void createDocument(int requestCode, RequestResultCallback callback, const QString &mimeType, const QString &displayName, const QString &initialUri = {});
void openDocument(int requestCode, const RequestResultCallback &callback, const QStringList &mimeTypes, const QString &initialUri = {});
void openDocuments(int requestCode, const RequestMultipleResultsCallback &callback, const QStringList &mimeTypes, const QString &initialUri = {});
void openDocumentTree(int requestCode, const RequestResultCallback &callback, const QString &initialUri = {});

public slots:
void createDocument(int requestCode, const QString &mimeType, const QString &displayName, const QString &initialUri = {});
void openDocument(int requestCode, const QStringList &mimeTypes, const QString &initialUri = {});
void openDocuments(int requestCode, const QStringList &mimeTypes, const QString &initialUri = {});
void openDocumentTree(int requestCode, const QString &initialUri = {});

signals:
void requestResult(int requestId, net::Uri uri);
void requestResults(int requestId, QList<net::Uri> uris);
};

} // namespace provider
Expand Down