1. 程式人生 > >Sharing Files on Android or iOS from or with your Qt App

Sharing Files on Android or iOS from or with your Qt App

Welcome to Part 4 of my Blog series about Sharing Files to and from mobile Qt Apps.

Part 1was about sharing Files or Content from your Qt App with native Android or iOS Apps,
Part 2 explained how to share Files with your Qt App from other native Android Apps,
Part 3 covered sharing Files with your Qt App from 

other native iOS Apps.
Part 4 implements FileProvider to share Files from your Qt App with native Android  Apps.

01_blog_overview

FileProvider Content URIs

Starting with Android 7 (SDK 24) you cannot use File URIs anymore to share Files to other Android Apps – you must use a FileProvider to share Files using a Content URI.

To avoid this you could use Target SDK 23 as I did for the first parts of this blog.

But starting November 1, 2018 Google requires for updates to Apps or new Apps on Google Play to target Android 8 (Oreo, API level 26) or higher, so there’s no way to share Files on Android without using a FileProvider.

Here’s the workflow to update your sharing App from File URI to FileProvider with Content URI.

 Android Manifest

As a first step we have to add some info to .xml :

<application ...>
<provider android:name="android.support.v4.content.FileProvider"
android:authorities="org.ekkescorner.examples.sharex.fileprovider"
android:grantUriPermissions="true" android:exported="false">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths"/>
</provider>
</application>

The Provider needs the com.android.support.v4 Libraries. To include them, please add com.android.support to your build.gradle file:

dependencies{

...

compile'com.android.support:support-v4:25.3.1'

}

This will only work if you have installed the Android Support Repository.

In your QtCreator Preferences → Devices → Android, you get easy access to Android SDK Manager. Please check that under Extras the Android Support Repository is installed:

02__sdk_manager_support_lib

In your Android Manifest you see a reference to resources @xml/filepaths. You have to add a new File filepaths.xml under android/res/xml:

03_filepaths_xml

<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="my_shared_files" path="share_example_x_files/" />
</paths>

This is the mapping to the folder where Android will find your File to be shared. This Folder is inside your AppData Location. Remember: in blog part 1 we used a shared documents location to provide Files to other apps. Now for Android we don’t use a shared location but a path inside our AppData location. Starting the app I always check if the folder exists:

#if defined (Q_OS_IOS)
QString docLocationRoot = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).value(0);
#endif
#if defined(Q_OS_ANDROID)
QString docLocationRoot = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).value(0);
#endif
mDocumentsWorkPath = docLocationRoot.append("/share_example_x_files");
if (!QDir(mDocumentsWorkPath).exists()) {
// create the QDir
}

Last important part in Android Manifest specifies an Authority:

android:authorities="org.ekkescorner.examples.sharex.fileprovider"

This name must be unique – so it’s a good idea to use your package name and append .fileprovider.

 QShareUtils Java Code

As a last step you must do some small changes in QShareUtils.java.

Import FileProvider and ShareCompat from android.support:

import android.support.v4.content.FileProvider;

import android.support.v4.app.ShareCompat;

Reference the Authority as defined in AndroidManifest:

private static String AUTHORITY="org.ekkescorner.examples.sharex.fileprovider";

You must also create your Intents in a different way:

// the old way: Intent sendIntent = new Intent();

Intent sendIntent = ShareCompat.IntentBuilder.from(QtNative.activity()).getIntent();

You’re done