I have an application that uses Universal Image Loader to download photos from the Internet, cache them in data / data / com.myapp / cache and display them in ImageViews.
I also wanted to add sharing (WhatsApp, Facebook, Instagram, Dropbox, etc.) to my application, so I tried using this code:
Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_STREAM, photoUri); intent.setType("image/jpeg"); startActivity(Intent.createChooser(intent, "Share image"));
photoUri is the uri in the cache folder in which other applications do not have read permission.
So, I googled / stackoverflowed and found out that I need to use FileProvider.
I configured FileProvider as follows ( as it was written here ) in my manifest:
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.myapp.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
And paths.xml file:
<paths xmlns:android="http://schemas.android.com/apk/res/android"> <cache-path name="photo_cache" path="/"/> </paths>
Then I use the following code in my activity on the onClickListener button:
File photoFile = ImageLoader.getInstance().getDiscCache().get("HTTP LINK HERE"); // returns File of "/data/data/com.myapp/cache/-1301123243" Uri photoUri = FileProvider.getUriForFile(MyActivity.this, "com.myapp.fileprovider", photoFile); // returns Uri of "content://com.myapp.fileprovider/photo_cache/-1301123243" photoUri = Uri.parse(photoUri.toString() + ".jpg"); // then I add .jpg to file name // Create intent Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_STREAM, photoUri); intent.setType("image/jpeg"); // Grant permissions to all apps that can handle this intent // thanks to this answer http://stackoverflow.com/a/18332000 List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); for (ResolveInfo resolveInfo : resInfoList) { String packageName = resolveInfo.activityInfo.packageName; grantUriPermission(packageName, photoUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); } // And start startActivity(Intent.createChooser(intent, "Share image"));
However, depending on the application, I get strange exceptions. Like this:
1974-1974/com.whatsapp W/Bundle﹕ Key android.intent.extra.STREAM expected ArrayList but value was a android.net.Uri$HierarchicalUri. The default value <null> was returned. 1974-1974/com.whatsapp W/Bundle﹕ Attempt to cast generated internal exception: java.lang.ClassCastException: android.net.Uri$HierarchicalUri cannot be cast to java.util.ArrayList at android.os.Bundle.getParcelableArrayList(Bundle.java:1223) at android.content.Intent.getParcelableArrayListExtra(Intent.java:4425) at com.whatsapp.ContactPicker.d(ContactPicker.java:320) at com.whatsapp.ContactPicker.onCreate(ContactPicker.java:306) at android.app.Activity.performCreate(Activity.java:5104)
Or I just see logs like this:
591-963/system_process W/ActivityManager﹕ Permission denied: checkComponentPermission()
And, of course, the applications themselves give me toasts with errors (they cannot open or download the file).
I tried googled, stackoverflowed LOT, so now I am posting here. I guess I'm doing everything right, maybe just something is wrong ...
Any help would be appreciated!