正确将可绘制图像共享到其他应用程序(没有FileProvider的情况下,将PNG共享到Whatsapp失败)

owl*_*ipe 2 java android android-intent whatsapp android-studio

我正在创建一个Android应用,用户可以在其中选择几张要共享的图像(存储在该drawable文件夹中),然后该应用打开一个标准的ACTION_SEND选择器,以允许他们将其共享到任何支持PNG的应用中,例如:

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;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果用户选择将其共享给Whatsapp,它将无法正常工作:与其将其解释为图像(例如,如果您通常与Whatsapp共享照片),不如将其解释为图像,该文档称为“无标题”,并且不会显示作为图像。

Whatsapp问题

在计算机上打开此“无标题”文档将显示该文档名为“ DOC-20180721-WA0012.无文件扩展名”!手动png在文件名的末尾添加a 将显示正确的图像。

使这个怪异的(但绝对可以解决!):

  • 例如,如果用户选择在SMS应用程序中打开图像,则图像会正常显示。

  • 这发生在多种设备上(P beta上的Pixel 2和7.1.1上的Nokia 2)

  • 在其他应用程序中不会发生此问题,在其他应用程序中,PNG可以像正常图像一样通过Whatsapp发送(尽管它们似乎确实被Whatsapp自动转换为JPEG)。


我该怎么做才能确保Whatsapp将我的图片视为正确的PNG文件?另外,如何正确共享应用程序中预加载的图像,以便每个应用程序都能正确解释它?

owl*_*ipe 7

我通过正确实现FileProvider解决了这个问题!本指南对我有很大帮助,但在这里我将做一个简短的总结。

application清单的标签中,开始像这样声明新的FileProvider:

<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>
Run Code Online (Sandbox Code Playgroud)

然后,创建一个新目录xmlres在Android Studio中,按住Control键并单击,然后转到“新建”>“目录”)。然后,创建中的一个新的文件xml名为file_provider_paths(上新的控制点击xml目录,并转到新建>文件,并将其命名file_provider_paths.xml)。将此代码添加到该新的xml文件中:

<paths>
    <cache-path name="cache" path="/" />
    <files-path name="files" path="/" />
</paths>
Run Code Online (Sandbox Code Playgroud)

最后,在您的MainActivity或类似的地方使用它:

// 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"));
Run Code Online (Sandbox Code Playgroud)

为了imageFiledrawable目录中的图像中获取图像,我首先将其转换为位图,然后转换为File对象,如下所示:

// 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);
}
Run Code Online (Sandbox Code Playgroud)

完成后,每个应用程序现在都可以看到您的共享图像!