Skip to content

Commit

Permalink
WIP: basename on android
Browse files Browse the repository at this point in the history
TODO:
- Integrate for file transfers (let UI pass target filename)
- Refresh elsewhere as well
- Provide fallback if permission expired
- Expose proper API
  • Loading branch information
Vogtinator committed Nov 4, 2022
1 parent ab93003 commit 00a1fb3
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
51 changes: 51 additions & 0 deletions core/os/os-android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <QAndroidJniObject>
#include <QAndroidJniEnvironment>
#include <QAndroidActivityResultReceiver>
#include <QScopeGuard>

#include "os.h"

Expand Down Expand Up @@ -78,3 +79,53 @@ FILE *fopen_utf8(const char *path, const char *mode)

return fdopen(fd, mode);
}

char *android_basename(const char *path)
{
const char pattern[] = "content:";
if(strncmp(pattern, path, sizeof(pattern)-1) != 0)
return nullptr;

QAndroidJniObject jpath = QAndroidJniObject::fromString(QString::fromUtf8(path));
QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod(
"android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;",
jpath.object<jstring>());

QAndroidJniObject contentResolver = QtAndroid::androidActivity()
.callObjectMethod("getContentResolver",
"()Landroid/content/ContentResolver;");

QAndroidJniEnvironment env;
QAndroidJniObject col = QAndroidJniObject::getStaticObjectField("android/provider/OpenableColumns", "DISPLAY_NAME", "Ljava/lang/String;");
QAndroidJniObject proj = env->NewObjectArray(1, env->FindClass("java/lang/String"), col.object<jstring>());

QAndroidJniObject cursor = contentResolver.callObjectMethod("query", "(Landroid/net/Uri;[Ljava/lang/String;Landroid/os/Bundle;Landroid/os/CancellationSignal;)Landroid/database/Cursor;", uri.object<jobject>(), proj.object<jobject>(), nullptr, nullptr);
if (env->ExceptionCheck())
{
env->ExceptionDescribe();
env->ExceptionClear();
return nullptr;
}

if(!cursor.isValid())
return nullptr;

auto closeCursor = qScopeGuard([&] { cursor.callMethod<void>("close", "()V"); });

bool hasContent = cursor.callMethod<jboolean>("moveToFirst", "()Z");
if (env->ExceptionCheck())
{
env->ExceptionDescribe();
env->ExceptionClear();
return nullptr;
}

if(!hasContent)
return nullptr;

QAndroidJniObject name = cursor.callObjectMethod("getString", "(I)Ljava/lang/String;", 0);
if (!name.isValid())
return nullptr;

return strdup(name.toString().toUtf8().data());
}
2 changes: 1 addition & 1 deletion qml/Firebird/UIComponents/FileSelect.qml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ RowLayout {
Layout.preferredWidth: 100

font.italic: filePath === ""
text: filePath === "" ? qsTr("(none)") : Emu.basename(filePath)
text: { forceRefresh; return filePath === "" ? qsTr("(none)") : Emu.basename(filePath); }
color: { forceRefresh; return ((!selectExisting && Emu.saveDialogSupported()) || filePath === "" || Emu.fileExists(filePath)) ? paletteActive.text : "red"; }
}

Expand Down
14 changes: 6 additions & 8 deletions qmlbridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,14 +286,12 @@ QString QMLBridge::basename(QString path)
if(path.isEmpty())
return tr("None");

if(path.startsWith(QStringLiteral("content://")))
{
auto parts = path.splitRef(QStringLiteral("%2F"), QString::SkipEmptyParts, Qt::CaseInsensitive);
if(parts.length() > 1)
return parts.last().toString();

return tr("(Android File)");
}
#ifdef Q_OS_ANDROID
extern char *android_basename(const char *path);
QScopedPointer<char, QScopedPointerPodDeleter> android_bn{android_basename(path.toUtf8().data())};
if(android_bn)
return QString::fromUtf8(android_bn.data());
#endif

return QFileInfo(path).fileName();
}
Expand Down

0 comments on commit 00a1fb3

Please sign in to comment.