summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Schmertmann <Lars.Schmertmann@governikus.de>2020-05-30 19:45:59 +0200
committerLars Schmertmann <Lars.Schmertmann@governikus.de>2021-09-10 06:41:15 +0200
commitf2b914afc6a5ba4aa2f8dcd13a979f04f07034c2 (patch)
tree287fe6a90f58c4ff4d83eec2f30943b90c96ee1e
parent5083d9dcd635346363a10c886abee3e99b21d9be (diff)
Android: Enable QDesktopService
QDesktopServices::openUrl(const QUrl &url) is already implemented on Android. But even if it is possible to set an URL handler, the mechanism to invoke it is missing. With this commit the URL handler will work on Android like it is already working on iOS. Task-number: QTBUG-84382 Pick-to: 6.2 Change-Id: Ic560bd380f1cc59586861aa1a6a3ea064276a39e Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
-rw-r--r--doc/global/externalsites/external-resources.qdoc20
-rw-r--r--src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp26
-rw-r--r--src/gui/util/qdesktopservices.cpp51
-rw-r--r--src/plugins/platforms/android/qandroidplatformservices.cpp37
-rw-r--r--src/plugins/platforms/android/qandroidplatformservices.h14
5 files changed, 134 insertions, 14 deletions
diff --git a/doc/global/externalsites/external-resources.qdoc b/doc/global/externalsites/external-resources.qdoc
index f3682e593a..b952b753b8 100644
--- a/doc/global/externalsites/external-resources.qdoc
+++ b/doc/global/externalsites/external-resources.qdoc
@@ -45,6 +45,26 @@
\title Android: Query for devices
*/
/*!
+ \externalpage https://developer.android.com/training/app-links/deep-linking
+ \title Android: Create Deep Links to App Content
+*/
+/*!
+ \externalpage https://developer.android.com/training/app-links/verify-site-associations
+ \title Android: Verify Android App Links
+*/
+/*!
+ \externalpage https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl
+ \title iOS: canOpenURL:
+*/
+/*!
+ \externalpage https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app
+ \title iOS: Defining a Custom URL Scheme for Your App
+*/
+/*!
+ \externalpage https://developer.apple.com/documentation/xcode/supporting-associated-domains
+ \title iOS: Supporting Associated Domains
+*/
+/*!
\externalpage http://www.freedesktop.org/
\title freedesktop.org
*/
diff --git a/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp b/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp
index 0809d62da9..f1aff54fea 100644
--- a/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp
+++ b/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp
@@ -144,7 +144,31 @@ QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
}
//! [8]
-*/ // comment wrapper 3
+//! [9]
+<intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="https" android:host="your.domain.com" android:port="1337" android:path="/help"/>
+</intent-filter>
+//! [9]
+
+//! [10]
+<intent-filter android:autoVerify="true">
+//! [10]
+
+//! [11]
+[{
+ "relation": ["delegate_permission/common.handle_all_urls"],
+ "target": {
+ "namespace": "android_app",
+ "package_name": "com.example.app",
+ "sha256_cert_fingerprints":
+ ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
+ }
+}]
+//! [11]
+*/ // comment wrapper 3
} // src_gui_util_qdesktopservices
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index 0550cb6f75..7a728cf692 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -182,7 +182,7 @@ void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler)
\warning URLs passed to this function on iOS will not load unless their schemes are
listed in the \c LSApplicationQueriesSchemes key of the application's Info.plist file.
For more information, see the Apple Developer Documentation for
- \l{https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl}{canOpenURL(_:)}.
+ \l {iOS: canOpenURL:}{canOpenURL:}.
For example, the following lines enable URLs with the HTTPS scheme:
\snippet code/src_gui_util_qdesktopservices.cpp 3
@@ -244,14 +244,25 @@ bool QDesktopServices::openUrl(const QUrl &url)
\snippet code/src_gui_util_qdesktopservices.cpp 0
+ If setUrlHandler() is used to set a new handler for a scheme which already
+ has a handler, the existing handler is simply replaced with the new one.
+ Since QDesktopServices does not take ownership of handlers, no objects are
+ deleted when a handler is replaced.
+
+ Note that the handler will always be called from within the same thread that
+ calls QDesktopServices::openUrl().
+
+ \section1 iOS
+
To use this function for receiving data from other apps on iOS you also need to
add the custom scheme to the \c CFBundleURLSchemes list in your Info.plist file:
\snippet code/src_gui_util_qdesktopservices.cpp 4
For more information, see the Apple Developer Documentation for
- \l{https://developer.apple.com/documentation/uikit/core_app/allowing_apps_and_websites_to_link_to_your_content/communicating_with_other_apps_using_custom_urls?language=objc}{Communicating with Other Apps Using Custom URLs}.
- \warning It is not possible to claim support for some well known URL schemes, including http and https. This is only allowed for Universal Links.
+ \l {iOS: Defining a Custom URL Scheme for Your App}{Defining a Custom URL Scheme for Your App}.
+ \warning It is not possible to claim support for some well known URL schemes, including http and
+ https. This is only allowed for Universal Links.
To claim support for http and https the above entry in the Info.plist file
is not allowed. This is only possible when you add your domain to the
@@ -261,21 +272,39 @@ bool QDesktopServices::openUrl(const QUrl &url)
iOS will search for /.well-known/apple-app-site-association on your domain,
when the application is installed. If you want to listen to
- https://your.domain.com/help?topic=ABCDEF you need to provide the following
+ \c{https://your.domain.com/help?topic=ABCDEF} you need to provide the following
content there:
\snippet code/src_gui_util_qdesktopservices.cpp 8
For more information, see the Apple Developer Documentation for
- \l{https://developer.apple.com/documentation/safariservices/supporting_associated_domains_in_your_app}[Supporting Associated Domains}.
+ \l {iOS: Supporting Associated Domains}{Supporting Associated Domains}.
- If setUrlHandler() is used to set a new handler for a scheme which already
- has a handler, the existing handler is simply replaced with the new one.
- Since QDesktopServices does not take ownership of handlers, no objects are
- deleted when a handler is replaced.
+ \section1 Android
- Note that the handler will always be called from within the same thread that
- calls QDesktopServices::openUrl().
+ To use this function for receiving data from other apps on Android, you
+ need to add one or more intent filter to the \c activity in your app manifest:
+
+ \snippet code/src_gui_util_qdesktopservices.cpp 9
+
+ For more information, see the Android Developer Documentation for
+ \l {Android: Create Deep Links to App Content}{Create Deep Links to App Content}.
+
+ To immediately open the corresponding content in your Android app, without
+ requiring the user to select the app, you need to verify your link. To
+ enable the verification, add an additional parameter to your intent filter:
+
+ \snippet code/src_gui_util_qdesktopservices.cpp 10
+
+ Android will look for \c{https://your.domain.com/.well-known/assetlinks.json},
+ when the application is installed. If you want to listen to
+ \c{https://your.domain.com:1337/help}, you need to provide the following
+ content there:
+
+ \snippet code/src_gui_util_qdesktopservices.cpp 11
+
+ For more information, see the Android Developer Documentation for
+ \l {Android: Verify Android App Links}{Verify Android App Links}.
\sa openUrl(), unsetUrlHandler()
*/
diff --git a/src/plugins/platforms/android/qandroidplatformservices.cpp b/src/plugins/platforms/android/qandroidplatformservices.cpp
index 36e1aef609..8c2af5fff4 100644
--- a/src/plugins/platforms/android/qandroidplatformservices.cpp
+++ b/src/plugins/platforms/android/qandroidplatformservices.cpp
@@ -41,16 +41,32 @@
#include "qandroidplatformservices.h"
#include <QDebug>
+#include <QDesktopServices>
#include <QFile>
#include <QMimeDatabase>
-#include <QUrl>
#include <QtCore/QJniObject>
#include <QtCore/qcoreapplication.h>
+#include <QtCore/qscopedvaluerollback.h>
QT_BEGIN_NAMESPACE
QAndroidPlatformServices::QAndroidPlatformServices()
{
+ m_actionView = QJniObject::getStaticObjectField("android/content/Intent", "ACTION_VIEW",
+ "Ljava/lang/String;")
+ .toString();
+
+ QtAndroidPrivate::registerNewIntentListener(this);
+
+ QMetaObject::invokeMethod(
+ this,
+ [this] {
+ QJniObject context = QJniObject(QtAndroidPrivate::context());
+ QJniObject intent =
+ context.callObjectMethod("getIntent", "()Landroid/content/Intent;");
+ handleNewIntent(nullptr, intent.object());
+ },
+ Qt::QueuedConnection);
}
bool QAndroidPlatformServices::openUrl(const QUrl &theUrl)
@@ -58,6 +74,10 @@ bool QAndroidPlatformServices::openUrl(const QUrl &theUrl)
QString mime;
QUrl url(theUrl);
+ // avoid recursing back into self
+ if (url == m_handlingUrl)
+ return false;
+
// if the file is local, we need to pass the MIME type, otherwise Android
// does not start an Intent to view this file
QLatin1String fileScheme("file");
@@ -87,4 +107,19 @@ QByteArray QAndroidPlatformServices::desktopEnvironment() const
return QByteArray("Android");
}
+bool QAndroidPlatformServices::handleNewIntent(JNIEnv *env, jobject intent)
+{
+ Q_UNUSED(env);
+
+ const QJniObject jniIntent(intent);
+
+ const QString action = jniIntent.callObjectMethod<jstring>("getAction").toString();
+ if (action != m_actionView)
+ return false;
+
+ const QString url = jniIntent.callObjectMethod<jstring>("getDataString").toString();
+ QScopedValueRollback<QUrl> rollback(m_handlingUrl, url);
+ return QDesktopServices::openUrl(url);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformservices.h b/src/plugins/platforms/android/qandroidplatformservices.h
index 6f2f0a394f..dff132d56d 100644
--- a/src/plugins/platforms/android/qandroidplatformservices.h
+++ b/src/plugins/platforms/android/qandroidplatformservices.h
@@ -42,16 +42,28 @@
#include <qpa/qplatformservices.h>
#include "androidjnimain.h"
+#include <QtCore/private/qjnihelpers_p.h>
+#include <QtCore/qobject.h>
+#include <QUrl>
QT_BEGIN_NAMESPACE
-class QAndroidPlatformServices: public QPlatformServices
+class QAndroidPlatformServices : public QObject,
+ public QPlatformServices,
+ public QtAndroidPrivate::NewIntentListener
{
public:
QAndroidPlatformServices();
+
bool openUrl(const QUrl &url) override;
bool openDocument(const QUrl &url) override;
QByteArray desktopEnvironment() const override;
+
+ bool handleNewIntent(JNIEnv *env, jobject intent) override;
+
+private:
+ QUrl m_handlingUrl;
+ QString m_actionView;
};
QT_END_NAMESPACE