android share image in ImageView without saving in sd card
The recommended method for sharing files with other apps is with a ContentProvider called FileProvider. The documentation is pretty good, but some parts are a little tricky. Here is a summary.
Set up the FileProvider in the Manifest
<manifest>
...
<application>
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
...
</application>
</manifest>
Replace com.example.myapp
with your app package name.
Create res/xml/filepaths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="shared_images" path="images/"/>
</paths>
This tells the FileProvider where to get the files to share (using the cache directory in this case).
Save the image to internal storage
// save bitmap to cache directory
try {
File cachePath = new File(context.getCacheDir(), "images");
cachePath.mkdirs(); // don't forget to make the directory
FileOutputStream stream = new FileOutputStream(new File(cachePath, "image.png")); // overwrites this image every time
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Share the image
File imagePath = new File(context.getCacheDir(), "images");
File newFile = new File(imagePath, "image.png");
Uri contentUri = FileProvider.getUriForFile(context, "com.example.app.fileprovider", newFile);
if (contentUri != null) {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // temp permission for receiving app to read this file
shareIntent.setDataAndType(contentUri, getContentResolver().getType(contentUri));
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
startActivity(Intent.createChooser(shareIntent, "Choose an app"));
}
Further reading
- FileProvider
- Storage Options - Internal Storage
- Sharing Files
- Saving Files
I was able to do this:
File file = new File( getCacheDir(), "screenshot.png");
...
file.setReadable(true, false);
Uri uri = Uri.fromFile(file);
...
intent.putExtra(Intent.EXTRA_STREAM, uri);
This way I save the file in my own cache folder, so I'm not fooling with any public folders or depending on the sd card being present.
Also, this way it gets deleted automatically if the user removes my app, but I also used startActivityForResult/onActivityResult to delete the file and set its folder back to private when the share is finished.
(Personally I was hoping to find a way to share a bitstream and avoid the step of creating a file entirely, but I don't think that is possible.)
[EDIT: I discovered this doesn't work on 2.3.6 where the file MUST be on file:///mnt/sdcard.]