This is what i'm using
I combined some answers and used the current AndroidX version/doku
Basic Process: You change the manifest to make it possible for other apps to access your local files. the filepath's that are allowed to be accessed from outside are found in the res/xml/filepaths.xml. When sharing you create an intent to share and set a Flag that temporarily allowed the other app to access your local files. Android documentation claims this is the secure way to share files
Step1: Add FileProvider to Manifest
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.YOUR.APP.PACKAGE.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
Step2: Add filepaths.xml to res/xml (if XML folder does not exists just create it yourself)
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path path="share/" name="share" />
</paths>
Step3: Use a function like this to start a file share. this function moves the file to the predefined share folder and creates a Url to it. the ShareDir is the File pointing to the files/share/ directory. the copy_File function copies the given file to the share directory in order to be accessible from the outside.
The function also makes it possible to Send the File as email with given header and body. if not needed just set it to empty strings
public void ShareFiles(Activity activity, List<File> files, String header, String body) {
ArrayList<Uri> uriList = new ArrayList<>();
if(files != null) {
for (File f : files) {
if (f.exists()) {
File file_in_share = copy_File(f, ShareDir);
if(file_in_share == null)
continue;
// Use the FileProvider to get a content URI
try {
Uri fileUri = FileProvider.getUriForFile(
activity,
"com.YOUR.APP.PACKAGE.fileprovider",
file_in_share);
uriList.add(fileUri);
} catch (IllegalArgumentException e) {
Log.e("File Selector",
"The selected file can't be shared: " + f.toString());
}
}
}
}
if(uriList.size() == 0)
{
Log.w("StorageModule", "ShareFiles: no files to share");
return;
}
Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setType("text/html");
intent.putExtra(Intent.EXTRA_SUBJECT, header);
intent.putExtra(Intent.EXTRA_TEXT, body);
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriList);
//fix for policy:
//https://stackoverflow.com/questions/48117511/exposed-beyond-app-through-clipdata-item-geturi
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
}
activity.startActivity(Intent.createChooser(intent, getR_String(R.string.share_files)));
}
If `targetSdkVersion` is higher than **24**, then [FileProvider][1] is used to grant access.
Create an xml file(Path: res\xml\) **provider_paths.xml**
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
<br>
Add a **Provider** in **[AndroidManifest.xml][2]**
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
If you are using **androidx**, the FileProvider path should be:
android:name="androidx.core.content.FileProvider"
and **replace**
Uri uri = Uri.fromFile(fileImagePath);
to
Uri uri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider",fileImagePath);
**Edit:** While you're including the URI with an `Intent` make sure to add below line:
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
and you are good to go. Hope it helps.
[1]: https://www.google.co.in/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwjiyKWypuDVAhVIso8KHcA2BvIQFgglMAA&url=https%3A%2F%2Fdeveloper.android.com%2Freference%2Fandroid%2Fsupport%2Fv4%2Fcontent%2FFileProvider.html&usg=AFQjCNEBbyss3j2b0k_XQncN1I9vLhrlGQ
[2]: https://developer.android.com/guide/topics/manifest/manifest-intro.html