Android: use FileProvider with QDesktopServices::openUrl()
Allow openUrl() to use FileProvider for opening files that are located under app scoped paths and that use a file scheme for Android sdk 24 or above. [ChangeLog][Core][Android] Add FileProvider support for QDesktopServices::openUrl(). [ChangeLog][Core][Android] Add AndroidX dependency to Gradle builds by default since it's required by FileProvider. Fixes: QTBUG-85238 Change-Id: Ia7403f74f2a8fd4886f74dba72e42b318ef5d079 Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com> Reviewed-by: Nicholas Bennett <nicholas.bennett@qt.io> Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>bb10
parent
b8d51001f7
commit
738c48244b
|
|
@ -12,3 +12,6 @@ org.gradle.parallel=true
|
|||
# build with the same inputs. However, over time, the cache size will
|
||||
# grow. Uncomment the following line to enable it.
|
||||
#org.gradle.caching=true
|
||||
|
||||
# Allow AndroidX usage
|
||||
android.useAndroidX=true
|
||||
|
|
|
|||
|
|
@ -43,5 +43,15 @@
|
|||
android:name="android.app.extract_android_style"
|
||||
android:value="minimal" />
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.qtprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/qtprovider_paths"/>
|
||||
</provider>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ add_custom_target(Qt${QtBase_VERSION_MAJOR}AndroidTemplates
|
|||
SOURCES
|
||||
${template_files}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/res/values/libs.xml"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/res/xml/qtprovider_paths.xml"
|
||||
)
|
||||
|
||||
qt_path_join(destination ${QT_INSTALL_DIR} ${INSTALL_DATADIR} "src/android/templates")
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ apply plugin: 'com.android.application'
|
|||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
||||
implementation 'androidx.core:core:1.8.0'
|
||||
}
|
||||
|
||||
android {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<files-path name="files_path" path="/"/>
|
||||
</paths>
|
||||
|
|
@ -46,3 +46,13 @@
|
|||
\externalpage https://www.lunarg.com/vulkan-sdk/
|
||||
\title LunarG Vulkan SDK
|
||||
*/
|
||||
|
||||
/*!
|
||||
\externalpage https://developer.android.com/reference/androidx/core/content/FileProvider
|
||||
\title Android: FileProvider
|
||||
*/
|
||||
|
||||
/*!
|
||||
\externalpage https://developer.android.com/training/secure-file-sharing/setup-sharing.html
|
||||
\title Android: Setting up file sharing
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -162,6 +162,13 @@ void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler)
|
|||
|
||||
\snippet code/src_gui_util_qdesktopservices.cpp 3
|
||||
|
||||
\note For Android Nougat (SDK 24) and above, URLs with a \c file scheme
|
||||
are opened using \l {Android: FileProvider}{FileProvider} which tries to obtain
|
||||
a shareable \c content scheme URI first. For that reason, Qt for Android defines
|
||||
a file provider with the authority \c ${applicationId}.qtprovider, with \c applicationId
|
||||
being the app's package name to avoid name conflicts. For more information, also see
|
||||
\l {Android: Setting up file sharing}{Setting up file sharing}.
|
||||
|
||||
\sa setUrlHandler()
|
||||
*/
|
||||
bool QDesktopServices::openUrl(const QUrl &url)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@ QAndroidPlatformServices::QAndroidPlatformServices()
|
|||
Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
Q_DECLARE_JNI_TYPE(UriType, "Landroid/net/Uri;")
|
||||
Q_DECLARE_JNI_TYPE(FileType, "Ljava/io/File;")
|
||||
Q_DECLARE_JNI_CLASS(File, "java/io/File")
|
||||
Q_DECLARE_JNI_CLASS(FileProvider, "androidx/core/content/FileProvider");
|
||||
|
||||
bool QAndroidPlatformServices::openUrl(const QUrl &theUrl)
|
||||
{
|
||||
QString mime;
|
||||
|
|
@ -55,13 +60,36 @@ bool QAndroidPlatformServices::openUrl(const QUrl &theUrl)
|
|||
if (url.scheme() == fileScheme)
|
||||
mime = QMimeDatabase().mimeTypeForUrl(url).name();
|
||||
|
||||
const QJniObject mimeString = QJniObject::fromString(mime);
|
||||
|
||||
using namespace QNativeInterface;
|
||||
QJniObject urlString = QJniObject::fromString(url.toString());
|
||||
QJniObject mimeString = QJniObject::fromString(mime);
|
||||
return QJniObject::callStaticMethod<jboolean>(
|
||||
QtAndroid::applicationClass(), "openURL",
|
||||
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)Z",
|
||||
QAndroidApplication::context(), urlString.object(), mimeString.object());
|
||||
|
||||
auto openUrl = [mimeString](const QJniObject &url) {
|
||||
return QJniObject::callStaticMethod<jboolean>(QtAndroid::applicationClass(), "openURL",
|
||||
QAndroidApplication::context(), url.object<jstring>(), mimeString.object<jstring>());
|
||||
};
|
||||
|
||||
if (url.scheme() != fileScheme || QNativeInterface::QAndroidApplication::sdkVersion() < 24)
|
||||
return openUrl(QJniObject::fromString(url.toString()));
|
||||
|
||||
// Use FileProvider for file scheme with sdk >= 24
|
||||
const QJniObject context = QAndroidApplication::context();
|
||||
const auto appId = context.callMethod<jstring>("getPackageName").toString();
|
||||
const auto providerName = QJniObject::fromString(appId + ".qtprovider"_L1);
|
||||
|
||||
const auto urlPath = QJniObject::fromString(url.path());
|
||||
const auto urlFile = QJniObject(QtJniTypes::className<QtJniTypes::File>(),
|
||||
urlPath.object<jstring>());
|
||||
|
||||
const auto fileProviderUri = QJniObject::callStaticMethod<QtJniTypes::UriType>(
|
||||
QtJniTypes::className<QtJniTypes::FileProvider>(), "getUriForFile",
|
||||
QAndroidApplication::context(), providerName.object<jstring>(),
|
||||
urlFile.object<QtJniTypes::FileType>());
|
||||
|
||||
if (fileProviderUri.isValid())
|
||||
return openUrl(fileProviderUri.callMethod<jstring>("toString"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QAndroidPlatformServices::openDocument(const QUrl &url)
|
||||
|
|
|
|||
Loading…
Reference in New Issue