使用FileProvider共享缓存图像

6
我有一个应用程序使用Universal Image Loader从互联网下载照片,将它们缓存到data/data/com.myapp/cache并在ImageViews中显示。
我还想在我的应用程序中添加共享功能(WhatsApp、Facebook、Instagram、Dropbox等),因此我尝试使用以下代码:
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是缓存文件夹中的uri,其他应用程序没有读取权限。

所以我在谷歌/stackoverflow上搜索并找到了答案,需要使用FileProvider。

我在清单文件中按照这里的说明进行了FileProvider的配置:

<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>

还有file_paths.xml文件:

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

然后我在我的活动中使用以下代码在按钮的 onClickListener 中:

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 https://dev59.com/UmMl5IYBdhLWcg3woYPa#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"));

然而,根据应用程序的不同,我会遇到一些奇怪的异常情况。就像这样:

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)

或者我只看到这样的日志:

591-963/system_process W/ActivityManager﹕ Permission denied: checkComponentPermission()

当然,应用程序本身也会向我发送错误提示(无法打开或下载文件)。

我尝试过很多方法,包括谷歌和stackoverflow,现在我来到这里发帖求助。我想我做得没错,可能只是有些小问题...

非常感谢您的帮助!


你可以在Android的XML文件中添加Internet权限吗? - Riskhan
@kTekkie,我认为你没有正确理解问题,抱歉。 - Makks129
@Makks129,你是在使用JSON获取图片吗?如果是的话,能否与我分享一份示例代码,或者是否有类似的代码可以在Github上fork?我的需求是:在GridView中使用Universal Image Loader + JSON,不想使用固定的图片链接。 - Sun
1个回答

0

我认为这可能是FileProvider基础设施或您共享的应用程序的问题。

我一直在尝试使用此支持与其他应用程序共享图像。它可以在Gallery、Drive、Gmail和Keep中正常工作,但在Photos和Google+中失败。

我在LogCat中看到以下条目,这让我相信Uri正在从一个Activity传递到另一个Activity。然而,Intent中设置的(临时)权限被丢失了。

11-19 21:14:06.031: I/ActivityManager(433): Displayed com.google.android.apps.plus/.phone.HostPhotoViewIntentActivity: +848ms


你在 Instagram、Facebook 或 Messenger 上尝试过这种方法吗?它应该可以工作,但似乎并没有。 - Mario Lenci

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接