Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android 6: cannot share files anymore?

I am sharing an image, and this code works properly for devices before Android 6:

Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.setType("image/*"); Uri uri = Uri.fromFile(new File(mFilename)); shareIntent.putExtra(Intent.EXTRA_STREAM, uri); mContext.startActivity(Intent.createChooser(shareIntent, mChooserTitle)); 

However I get the toast error "can't attach empty files" when I try to share using Android 6.

I verified that the file exists and it's not zero-length.

Anyone has a solution for this?

like image 391
Daniele B Avatar asked Oct 06 '15 23:10

Daniele B


People also ask

Why can't I open downloaded files on my Android phone?

If a file won't open, a few things could be wrong: You don't have permission to view the file. You're signed in to a Google Account that doesn't have access. The correct app isn't installed on your phone.

How do I share between iPhone and Android?

Download and install the Smart Transfer app on your Android (from the Google Play Store) and on your iPhone (from the Apple App Store). Open Smart Transfer on your Android and tap the Send button. Launch Smart Transfer on the iPhone and tap the receive button. Choose whether to connect via Hotspot or Wi-Fi.


2 Answers

I solved it by implementing a FileProvider, as suggested by @CommonsWare

You first need to configure a FileProvider:

  • first, add the <provider> to your file manifest XML

    <provider     android:name="android.support.v4.content.FileProvider"     android:authorities="com.myfileprovider"     android:exported="false"     android:grantUriPermissions="true">     <meta-data         android:name="android.support.FILE_PROVIDER_PATHS"         android:resource="@xml/file_provider_paths" /> </provider> 
  • second, define your file paths in a separate XML file, I called it "file_provider_paths.xml"

    <paths xmlns:android="http://schemas.android.com/apk/res/android">     <external-path name="share" path="/" /> </paths> 

you can find the complete explanation in this documentation page

after you have set up your file provider in XML, this is the code to share the image file:

Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.setType("image/*"); Uri fileUri = FileProvider.getUriForFile(mContext, "com.myfileprovider", new File(mFilename)); shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri); mContext.startActivity(Intent.createChooser(shareIntent, mChooserTitle)); 
like image 175
Daniele B Avatar answered Sep 19 '22 08:09

Daniele B


One limitation of the Android 6.0 runtime permission system is that there will be corner cases that cause problems. What you encountered is one: trying to share a file on external storage to an app that does not have the runtime permission checks in place for that particular UI path.

I say that this is a "corner case" because, for this bug in the receiving app to affect the user, the user cannot have previously used that app and granted the necessary permission. Either:

  • The user has never used that app before, yet it still trying to share content to it, or

  • The user revoked the permission via Settings, but did not realize that it would break this bit of functionality

Both of those are low probability events.

You, as the sender, have two main options:

  1. Switch away from using file:// Uri values, in favor of a file-serving ContentProvider like FileProvider, so the permission is no longer needed, or

  2. Just living with the corner case

like image 44
CommonsWare Avatar answered Sep 21 '22 08:09

CommonsWare