diff --git a/app/src/core/ToolProvider.h b/app/src/core/ToolProvider.h index 08a6f1f..e46417e 100644 --- a/app/src/core/ToolProvider.h +++ b/app/src/core/ToolProvider.h @@ -97,6 +97,12 @@ bool hasAllFilesAccess(); * dialog for it). A desktop, a phone that already has it or one too old to * know about it returns "" and nothing opens. */ QString requestAllFilesAccess(); +/* The arguments the Android activity was started with (the + * "applicationArguments" intent extra): the way + * `cst-agent-app --uitest --workspace DIR` is reachable on a device, since + * Qt's own plumbing for that extra does not reach this build. Empty + * everywhere else, and empty on a device that was not started with any. */ +QStringList activityArguments(); } // namespace app diff --git a/app/src/main.cpp b/app/src/main.cpp index 44b532c..541eb72 100644 --- a/app/src/main.cpp +++ b/app/src/main.cpp @@ -199,7 +199,16 @@ int main(int argc, char **argv) { parser.addOption(planOpt); parser.addOption(uitestOpt); parser.addOption(sizeOpt); - parser.process(app); + /* What the process was started with, plus -- on a phone -- what the + * activity was started with: Qt's own applicationArguments plumbing does + * not deliver the extra on the NX789J (see activityArguments()), and + * without it there is no way to hand this window a workspace or a --uitest + * run on a device that has no keyboard. */ + QStringList args = QCoreApplication::arguments(); +#if defined(Q_OS_ANDROID) + args += app::activityArguments(); +#endif + parser.process(args); QString ws = parser.value(wsOpt); if (ws.isEmpty()) { diff --git a/app/src/platform/android/AndroidTools.cpp b/app/src/platform/android/AndroidTools.cpp index 96c109b..47c6b86 100644 --- a/app/src/platform/android/AndroidTools.cpp +++ b/app/src/platform/android/AndroidTools.cpp @@ -101,6 +101,41 @@ QJniObject appContext() { return QNativeInterface::QAndroidApplication::context(); } +/* The strings the activity was started with. Qt is meant to hand the + * "applicationArguments" extra to QCoreApplication::arguments() by itself; on + * the NX789J it does not -- `am start ... --esa applicationArguments + * "--workspace,/sdcard/x"` left the window on its default workspace, and so + * did the same extra as a plain string. So the intent is asked directly, which + * is what makes `cst-agent-app --uitest --workspace DIR` (or any other + * argument) reachable on a device with no keyboard attached. + * + * Everything here degrades to "no arguments": an invalid object, a missing + * method, or a context that is not an activity all come back empty. */ +QStringList intentArguments() { + QStringList out; + QJniObject activity = appContext(); + if (!activity.isValid()) + return out; + QJniObject intent = + activity.callObjectMethod("getIntent", "()Landroid/content/Intent;"); + if (!intent.isValid()) + return out; + QJniObject list = intent.callObjectMethod( + "getStringArrayListExtra", "(Ljava/lang/String;)Ljava/util/ArrayList;", + QJniObject::fromString(QStringLiteral("applicationArguments")) + .object()); + if (!list.isValid()) + return out; + const jint n = list.callMethod("size", "()I"); + for (jint i = 0; i < n; i++) { + QJniObject item = + list.callObjectMethod("get", "(I)Ljava/lang/Object;", i); + if (item.isValid()) + out << item.toString(); + } + return out; +} + /* --- notification_send --------------------------------------------------- */ /* Android 13 (API 33) put notifications behind a runtime permission; before @@ -516,6 +551,11 @@ cst_tool_def_t g_share; } // namespace +/* What main() asks for (ToolProvider.h): the reading itself is the JNI helper + * above, next to the Android context it needs. It sits outside the anonymous + * namespace so main.cpp can link to it. */ +QStringList activityArguments() { return intentArguments(); } + /* A file card's "open": whatever app the phone has for the type, with the read * permission granted to the app that picks it up. */ QString openLocalFile(const QString &path, const QString &title,