8#if QT_CONFIG(desktopservices)
10#include <QDesktopServices>
12#include <QMimeDatabase>
13#include <QtCore/QJniObject>
14#include <QtCore/qcoreapplication.h>
15#include <QtCore/qscopedvaluerollback.h>
20using namespace QtJniTypes;
21using namespace Qt::StringLiterals;
23#if QT_CONFIG(desktopservices)
24static constexpr auto s_defaultScheme =
"file"_L1;
25static constexpr auto s_defaultProvider =
"qtprovider"_L1;
30#if QT_CONFIG(desktopservices)
31 m_actionView = QJniObject::getStaticObjectField(
"android/content/Intent",
"ACTION_VIEW",
35 QtAndroidPrivate::registerNewIntentListener(
this);
38 if (QNativeInterface::QAndroidApplication::isActivityContext()) {
39 QMetaObject::invokeMethod(
42 QJniObject context = QJniObject(QtAndroidPrivate::context());
44 context.callObjectMethod(
"getIntent",
"()Landroid/content/Intent;");
45 handleNewIntent(
nullptr, intent.object());
47 Qt::QueuedConnection);
54 return QByteArray(
"Android");
62#if QT_CONFIG(desktopservices)
63bool QAndroidPlatformServices::openUrl(
const QUrl &theUrl)
68 if (url == m_handlingUrl)
72 if (url.scheme().isEmpty())
73 url.setScheme(s_defaultScheme);
75 const int sdkVersion = QNativeInterface::QAndroidApplication::sdkVersion();
76 if (url.scheme() != s_defaultScheme || sdkVersion < 24 )
78 return openUrlWithFileProvider(url);
81QString QAndroidPlatformServices::getMimeOfUrl(
const QUrl &url)
const
84 if (url.scheme() == s_defaultScheme)
85 mime = QMimeDatabase().mimeTypeForUrl(url).name();
89bool QAndroidPlatformServices::openURL(
const QUrl &url)
const
91 return openURL(url.toString());
94bool QAndroidPlatformServices::openURL(
const QString &url)
const
96 return QJniObject::callStaticMethod<jboolean>(
97 QtAndroid::applicationClass(),
"openURL",
98 QNativeInterface::QAndroidApplication::context(),
103bool QAndroidPlatformServices::openUrlWithFileProvider(
const QUrl &url)
105 const QJniObject context = QNativeInterface::QAndroidApplication::context();
106 auto authorities = getFileProviderAuthorities(context);
107 if (authorities.isEmpty())
109 return openUrlWithAuthority(url, getAdequateFileproviderAuthority(authorities));
113QString QAndroidPlatformServices::getAdequateFileproviderAuthority(
const QStringList &authorities)
const
115 if (authorities.size() == 1)
116 return authorities[0];
118 QString nonQtAuthority;
119 for (
const auto &authority : authorities) {
120 if (!authority.endsWith(s_defaultProvider, Qt::CaseSensitive)) {
121 nonQtAuthority = authority;
125 return nonQtAuthority;
128bool QAndroidPlatformServices::openUrlWithAuthority(
const QUrl &url,
const QString &authority)
130 const auto urlPath = QJniObject::fromString(url.path());
131 const auto urlFile = QJniObject(Traits<File>::className(),
132 urlPath.object<jstring>());
133 const auto fileProviderUri = QJniObject::callStaticMethod<Uri>(
134 Traits<FileProvider>::className(),
"getUriForFile",
135 QNativeInterface::QAndroidApplication::context(), authority,
136 urlFile.object<File>());
137 if (fileProviderUri.isValid())
138 return openURL(fileProviderUri.toString());
142QStringList QAndroidPlatformServices::getFileProviderAuthorities(
const QJniObject &context)
const
144 QStringList authorityList;
146 const auto packageManager = context.callMethod<PackageManager>(
"getPackageManager");
147 const auto packageName = context.callMethod<QString>(
"getPackageName");
148 const auto packageInfo = packageManager.callMethod<PackageInfo>(
"getPackageInfo",
151 const auto providersArray = packageInfo.getField<ProviderInfo[]>(
"providers");
153 if (providersArray.isValid()) {
154 const auto className = Traits<FileProvider>::className();
155 for (
const auto &fileProvider : providersArray) {
156 auto providerName = fileProvider.getField<QString>(
"name");
157 if (providerName.replace(
".",
"/").contains(className.data())) {
158 const auto authority = fileProvider.getField<QString>(
"authority");
159 if (!authority.isEmpty())
160 authorityList << authority;
164 if (authorityList.isEmpty())
165 qWarning() <<
"No file provider found in the AndroidManifest.xml.";
167 return authorityList;
170bool QAndroidPlatformServices::openDocument(
const QUrl &url)
175bool QAndroidPlatformServices::handleNewIntent(JNIEnv *env, jobject intent)
179 const QJniObject jniIntent(intent);
181 const QString action = jniIntent.callObjectMethod<jstring>(
"getAction").toString();
182 if (action != m_actionView)
185 const QString url = jniIntent.callObjectMethod<jstring>(
"getDataString").toString();
186 QScopedValueRollback<QUrl> rollback(m_handlingUrl, url);
187 return QDesktopServices::openUrl(url);
Combined button and popup list for selecting options.
Q_DECLARE_JNI_CLASS(MotionEvent, "android/view/MotionEvent")