Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FileProvider.getUriForFile vs Uri.fromFile - is there other difference but permissions

In my Andoroid app I want to let the user send a file that my app has generated using whatever sending method the user prefers (e.g. Email, Skype, Viber, Bluetooth, etc) I am using Intent.ACTION_SEND as follows:

File readF = new File(fullFileName);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, getResources().getString(R.string.some_subject));
intent.putExtra(Intent.EXTRA_TEXT, getResources().getString(R.string.some_message_body));
Uri uri = FileProvider.getUriForFile(this, "my.package.fileprovider", readF);
intent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(intent, getResources().getString(R.string.some_info_message));

Which successfully sends files over Gmail, and Bluetooth, just as expected.

But when the user chooses Skype, the file is sent, but its name is changed

When the user chooses Viber nothing is sent.

If I change only the way I construct the Uri:

Uri uri = Uri.fromFile(new File("/some/publicly/available/file"));

Then the file is successfully sent both over Skype, and Viber, and the name is preserved.

So what is the difference in using FileProvider vs directly using a public file in Intent.

like image 475
Jeni Avatar asked Oct 18 '22 15:10

Jeni


1 Answers

I am using Intent.ACTION_SEND as follows:

I recommend that you add Intent.FLAG_GRANT_READ_URI_PERMISSION to that Intent.

Then the file is successfully sent both over Skype, and Viber, and the name is preserved.

Only until your targetSdkVersion climbs to 24 or higher, and you start running your app on Android 7.0+. Then, your app crashes with a FileUriExposedException.

Then the file is successfully sent both over Skype, and Viber, and the name is preserved.

For now, perhaps. The authors of those apps, and any others, are not obligated to maintain your filenames. They can do whatever they want, as it is their apps, not yours.

So what is the difference in using FileProvider vs directly using a public file in Intent.

FileProvider is roughly analogous to a Web server. It allows an app to share content to other apps, without those apps necessarily having direct access to the underlying files. Google is trying to get away from having external storage be a dumping ground for random crap in support of things like ACTION_SEND, and so on Android 7.0+, StrictMode is set up "out of the box" to crash the app if you try passing a file Uri (e.g., Uri.fromFile()).

like image 154
CommonsWare Avatar answered Oct 21 '22 05:10

CommonsWare