Android Tutorial Sharing files from your app with File Provider

Example was updated based on FileProvider class: https://www.b4x.com/android/forum/threads/class-fileprovider-share-files.97865/
See the above link if you are interested in sharing files from your app.

This tutorial explains the steps required to implement a file picker that other applications can use to select files or resources.

upload_2016-8-29_13-51-54.png
upload_2016-8-29_13-52-7.png
upload_2016-8-29_13-52-19.png


Starting from Android 7 - Nougat,it is not possible to share a file directly (file:// uri). It will result with a FileUriExposedException. This is relevant even if you don't set the targetSdkVersion to 24.

The solution is to use FileProvider from Android support library.

The steps required are:
1. Add an intent filter that will tell the OS that your app allows choosing content:
B4X:
'manifest editor.
'FilePicker is the name of the activity.
AddActivityText(FilePicker,
<intent-filter>
  <action android:name="android.intent.action.PICK" />
  <category android:name="android.intent.category.DEFAULT" />
  <data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
  <action android:name="android.intent.action.GET_CONTENT" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.OPENABLE" />
  <data android:mimeType="image/*" />
</intent-filter>
)


3. When the relevant activity is resumed it needs to check the starting intent type. If it is an android.intent.action.GET_CONTENT intent then it should allow the user to select the resource.

4. The resource is copied to the "shared" folder and a Uri is created and returned to the calling app.

See the attached example.

Tips:

- Make sure to run the app in release mode as the process might be killed when it is in the background.
- This solution is compatible with Android 4+ devices.
 

Attachments

  • FilePicker.zip
    31.6 KB · Views: 2,643
Last edited:

KMatle

Expert
Licensed User
Longtime User

JohnC

Expert
Licensed User
Longtime User
I tried using this FileProvider method to share file to the devices SMS app and I noticed the URI started with "Content://" instead of "File://".

This worked on the android 7.1 and 8.x, but I got an error in the receiving SMS app on my 4.4 that said something like "File not Supported".

So basically, starting in Aug, I need to set the target API to 26, and then my app needs to manually check to see if the device's OS is < 7 and if so, use the "File://" share method, but if the OS is 7+, then use this file provider share method?

Do I have this correct?
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. You should have started a new thread for these questions.
2. Tutorial about targetSdkVersion: https://www.b4x.com/android/forum/threads/87610/#content
3. The schemes are content:// and file://. The case is important.
4.
So basically, starting in Aug, I need to set the target API to 26, and then my app needs to manually check to see if the device's OS is < 7 and if so, use the "File://" share method, but if the OS is 7+, then use this file provider share method?

Do I have this correct?
No. FileProvider works with all versions of Android.
 

Alessandro71

Well-Known Member
Licensed User
Longtime User
All the sharing examples I’ve found deal with the shared directory, forcing copying the files first into it.
What if my app has already permissions to access files outside of the private app directory?
I have a lot of big files on the external root, on which I have permissions, to share. I’d like to avoid making copies of them in my shared and then deleting them.
Is there a way to put in the manifest an additional provider path, referring to an external dir?
 

Alessandro71

Well-Known Member
Licensed User
Longtime User
Looking at the FileProvider class, it look like the shared file is copied to the "shared" directory and never deleted.
It is necessary to wipe the shared directory from time to time, to avoid cluttering with old shared files?
 

JohnC

Expert
Licensed User
Longtime User
I would say yes, otherwise it will just get bigger with more and more files over time.

However, since you don't know exactly when the other app "gets" the file after your app shares it, you can't delete the file right away, otherwise it might be deleted before the other app gets it.

What I do in situations like this, is when my app starts up, I delete any "previous" files that are in the shared directory (that were placed there during the last app's "share" function). This way, the app cleans up after itself on every new run of the app.
 
Top