Android: Make it possible to open documents from Android

Include ad-hoc code to open files on Android.
This commit is contained in:
Aleix Pol 2018-05-18 01:44:18 +02:00
parent 9ca00505a5
commit 885e1f2269
7 changed files with 113 additions and 42 deletions

View file

@ -1,43 +1,16 @@
<?xml version='1.0' encoding='utf-8'?>
<manifest package="org.kde.okularkirigami" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.3.0" android:versionCode="9" android:installLocation="auto">
<application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Okular" android:icon="@drawable/icon">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation"
android:name="org.qtproject.qt5.android.bindings.QtActivity"
android:label="Okular"
android:hardwareAccelerated="true"
android:screenOrientation="unspecified">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="okularkirigami"/>
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="1"/>
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="1"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.load_local_libs" android:value="plugins/platforms/android/libqtforandroid.so:plugins/bearer/libqandroidbearer.so"/>
<meta-data android:name="android.app.load_local_jars" android:value="jar/QtAndroid.jar:jar/QtAndroidAccessibility.jar:jar/QtAndroid-bundled.jar:jar/QtAndroidAccessibility-bundled.jar:jar/QtAndroidBearer.jar:jar/QtAndroidBearer-bundled.jar"/>
<meta-data android:name="android.app.static_init_classes" android:value=""/>
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<!-- Messages maps -->
</activity>
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation"
android:name="org.kde.something.OpenFileActivity"
android:label="Okular"
android:hardwareAccelerated="true"
android:screenOrientation="unspecified">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter android:label="Okular">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>

View file

@ -6,6 +6,7 @@ import android.util.Log;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.net.Uri;
import android.app.Activity;
import org.qtproject.qt5.android.bindings.QtActivity;
@ -14,16 +15,13 @@ class FileClass
public static native void openUri(String uri);
}
public class OpenFileActivity extends QtActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent bundleIntent = getIntent();
if (bundleIntent == null)
public class OpenFileActivity extends QtActivity
{
private void displayUri(Uri uri)
{
if (uri == null)
return;
final String action = bundleIntent.getAction();
Uri uri = bundleIntent.getData();
if (!uri.getScheme().equals("file")) {
try {
ContentResolver resolver = getBaseContext().getContentResolver();
@ -33,11 +31,49 @@ public class OpenFileActivity extends QtActivity {
e.printStackTrace();
//TODO: emit warning that couldn't be opened
Log.v("Okular", "failed to open");
Log.e("Okular", "failed to open");
return;
}
}
Log.e("Okular", "opening url: " + uri.toString());
FileClass.openUri(uri.toString());
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent bundleIntent = getIntent();
if (bundleIntent == null)
return;
final String action = bundleIntent.getAction();
Log.v("Okular", "Starting action: " + action);
if (action == "android.intent.action.VIEW") {
displayUri(bundleIntent.getData());
}
}
private static int OpenDocumentRequest = 42;
public static void openFile(Activity context, String title, String mimes)
{
Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setType("application/pdf");
Log.v("Okular", "opening: " + mimes);
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimes.split(";"));
context.startActivityForResult(intent, OpenDocumentRequest);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
Log.v("Okular", "Activity Result: " + String.valueOf(requestCode) + " with code: " + String.valueOf(resultCode));
if (requestCode == OpenDocumentRequest) {
Uri uri = intent.getData();
Log.v("Okular", "Opening document: " + uri.toString());
displayUri(uri);
}
}
}

View file

@ -2,7 +2,9 @@ set(CMAKE_AUTORCC ON)
add_executable(okularkirigami main.cpp app.qrc)
target_link_libraries(okularkirigami Qt5::Widgets Qt5::Qml KF5::I18n)
if (ANDROID)
find_package(Qt5 COMPONENTS AndroidExtras)
target_sources(okularkirigami PRIVATE android.cpp)
target_link_libraries(okularkirigami Qt5::AndroidExtras)
endif()
install(TARGETS okularkirigami ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})

View file

@ -17,6 +17,32 @@
*************************************************************************************/
#include "android.h"
#include <QAndroidJniObject>
#include <QAndroidJniEnvironment>
#include <QStringList>
#include <QDebug>
static AndroidInstance* s_instance = nullptr;
void AndroidInstance::openFile(const QString &title, const QStringList &mimes)
{
s_instance = this;
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); //activity is valid
Q_ASSERT ( activity.isValid() );
QAndroidJniEnvironment _env;
QAndroidJniObject::callStaticMethod<void>("org/kde/something/OpenFileActivity",
"openFile",
"(Landroid/app/Activity;Ljava/lang/String;Ljava/lang/String;)V",
activity.object<jobject>(),
QAndroidJniObject::fromString(title).object<jstring>(),
QAndroidJniObject::fromString(mimes.join(';')).object<jstring>()
);
if (_env->ExceptionCheck()) {
_env->ExceptionClear();
qWarning() << "couldn't launch intent";
}
}
void Java_org_kde_something_FileClass_openUri(JNIEnv *env,
jobject /*obj*/,
@ -24,7 +50,11 @@ void Java_org_kde_something_FileClass_openUri(JNIEnv *env,
{
jboolean isCopy = false;
const char* utf = env->GetStringUTFChars(uri, &isCopy);
handler.openUri(QString::fromUtf8(utf));
const QString uriString = QString::fromUtf8(utf);
if (s_instance)
s_instance->openUri(QUrl(uriString));
else
handler.openUri(uriString);
env->ReleaseStringUTFChars(uri, utf);
}

View file

@ -19,7 +19,8 @@
#ifndef ANDROID_H
#define ANDROID_H
#include <QString>
#include <QObject>
#include <QUrl>
#include <jni.h>
class URIHandler {
@ -33,6 +34,16 @@ public:
static URIHandler handler;
class AndroidInstance : public QObject
{
Q_OBJECT
public:
Q_SCRIPTABLE void openFile(const QString &title, const QStringList &mimes);
Q_SIGNALS:
void openUri(const QUrl &uri);
};
extern "C" {
JNIEXPORT void JNICALL

View file

@ -49,8 +49,10 @@ int main(int argc, char *argv[])
QQmlApplicationEngine engine;
#ifdef __ANDROID__
qmlRegisterSingletonType<QObject>("org.kde.okular.app", 2, 0, "AndroidInstance", [](QQmlEngine*, QJSEngine*) -> QObject* { return new AndroidInstance; });
const QString uri = handler.m_lastUrl;
#else
qmlRegisterSingletonType<QObject>("org.kde.okular.app", 2, 0, "AndroidInstance", [](QQmlEngine*, QJSEngine*) -> QObject* { return new QObject; });
const QString uri = parser.positionalArguments().count() == 1
? QUrl::fromUserInput(parser.positionalArguments().constFirst(), {}, QUrl::AssumeLocalFile).toString()
: QString();

View file

@ -21,6 +21,7 @@ import QtQuick 2.1
import QtQuick.Dialogs 1.3 as QQD
import org.kde.okular 2.0 as Okular
import org.kde.kirigami 2.0 as Kirigami
import org.kde.okular.app 2.0
Kirigami.AbstractApplicationWindow {
id: fileBrowserRoot
@ -47,6 +48,22 @@ Kirigami.AbstractApplicationWindow {
onTriggered: {
fileDialog.open()
}
},
Kirigami.Action {
text: i18n("Open Android...")
icon.name: "document-open"
readonly property var p0: Connections {
target: AndroidInstance
enabled: AndroidInstance.hasOwnProperty("openFile")
onOpenUri: {
console.log("open uri!", uri)
documentItem.url = uri
}
}
onTriggered: {
// var mimetypes = Okular.Okular.mimeTypes.join(",")
AndroidInstance.openFile(i18n("Document to open..."), "*/*")
}
}
]
}