简体   繁体   中英

Share drawable image to other apps properly (sharing PNG to Whatsapp fails without FileProvider)

I'm creating an Android app where the user can select one of several images to share (which are stored in the drawable folder) and the app opens up a standard ACTION_SEND chooser to allow them to share it to any app that supports PNGs, like so:

Uri imageUri = Uri.parse("android.resource://com.owlswipe.imagesharer/" + getImage());

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
sendIntent.setType("image/png");
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(sendIntent, "share to an app"));

public int getImage() {
return R.drawable.firstimage;
}

However, if the user selects to share it to Whatsapp, it doesn't work properly: instead of interpreting it as an image (like if you normally share a photo to Whatsapp) it thinks it's a document called "Untitled" and does not show as an image.

Whatsapp问题

Opening this Untitled document on a computer reveals it's called DOC-20180721-WA0012. with no file extension! Manually adding a png to the end of the filename reveals the correct image.

Making this weirder (but definitely solvable somehow!):

  • If the user chooses to open the image in an SMS app, for example, the image appears normally.

  • This has happened with multiple devices (Pixel 2 on P beta and Nokia 2 on 7.1.1)

  • This issue does not happen with other apps, where PNGs can be sent via Whatsapp like a normal image (though they do seem to be automatically converted to JPEGs by Whatsapp).


What can I do to make sure Whatsapp sees my image as a proper PNG file? Alternatively, how do I properly share a pre-loaded image from my app such that every app can interpret it correctly?

I solved this by properly implementing a FileProvider! This guide helped me so much , but I'll give a brief summary here.

Within the application tag of your Manifest, start declaring your new FileProvider like so:

<provider
android:name="android.support.v4.content.FileProvider"
android:grantUriPermissions="true"
android:exported="false"
android:authorities="${applicationId}">

    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_provider_paths"/>

</provider>

Then, create a new directory called xml (control-click on your res in Android Studio and go to New > Directory). Then, create a new file within xml called file_provider_paths (control-click on the new xml directory, and go to New > File, and name it file_provider_paths.xml ). Add this code to that new xml file:

<paths>
    <cache-path name="cache" path="/" />
    <files-path name="files" path="/" />
</paths>

Finally, use it in your MainActivity or wherever like so:

// create new Intent
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);

// set flag to give temporary permission to external app to use your FileProvider
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

// generate URI, I defined authority as the application ID in the Manifest, the last param is file I want to open
Uri uri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID, imageFile);
intent.putExtra(Intent.EXTRA_STREAM, uri);

// Set type to only show apps that can open your PNG file
intent.setType("image/png");

// start activity!
startActivity(Intent.createChooser(intent, "send"));

To get that imageFile from an image in my drawable directory, I first converted it to a Bitmap, and then onto a File object, like so:

// create file from drawable image
Bitmap bm = BitmapFactory.decodeResource(this.getResources(), R.drawable.yourbeautifulimage);

File filesDir = getApplicationContext().getFilesDir();
File imageFile = new File(filesDir, "ABeautifulFilename.png");

OutputStream os;
try {
    os = new FileOutputStream(imageFile);
    bm.compress(Bitmap.CompressFormat.PNG, 100, os); // 100% quality
    os.flush();
    os.close();
} catch (Exception e) {
    Log.e(getClass().getSimpleName(), "Error writing bitmap", e);
}

And you're done, every app can see your shared image now!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM