android - 图像共享 Intent 适用于 Gmail,但会导致 FB 和 twitter 崩溃

标签 android android-intent android-sharing android-fileprovider

我正在尝试允许用户将图像共享给设备上的其他应用。该图像位于我的应用程序内部存储区域的 files/子目录中。它在 Gmail 上运行得很好,但 Facebook 和 Twitter 在响应我的 Intent 时都会崩溃。

编辑:Google+ 也可以正常工作。

这里是相关的代码部分。

在 Application.xml 中

<provider 
    android:name="android.support.v4.content.FileProvider"
    android:authorities="org.iforce2d.myapp.MyActivity"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>

xml/文件路径.xml

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

这是我 Activity 中的分享代码:

File imagePath = new File(getContext().getFilesDir(), "shared");
File newFile = new File(imagePath, "snapshot.jpg");
Uri contentUri = FileProvider.getUriForFile(getContext(),
                     "org.iforce2d.myapp.MyActivity", newFile);    

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("image/jpeg");
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

List<ResolveInfo> resInfos = 
    getPackageManager().queryIntentActivities(shareIntent,
                                              PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo info : resInfos) {
    getContext().grantUriPermission(info.activityInfo.packageName, 
                                    contentUri,
                                    Intent.FLAG_GRANT_READ_URI_PERMISSION);
}

startActivity(Intent.createChooser(shareIntent, "Share image..."));

记录时contentUri的值为:

content://org.iforce2d.myapp.MyActivity/shared/snapshot.jpg

我只使用 Gmail、Facebook 和 Twitter 作为接收应用程序进行了检查,但结果在各种操作系统版本(从 2.2.1 到 4.4.3)和 7 种设备(包括 Kindle)上都非常一致。

Gmail 运行良好。图片缩略图出现在邮件合成中,并在发送时成功附加到邮件中。

Twitter 和 Facebook 都崩溃了,如下所示。

这里是来自 logcat 的堆栈跟踪,显示了这两个应用程序遇到的问题,它们似乎都是相同的问题(取自 4.4.3,但错误实际上一直是相同的到 2.2.1 尽管错误消息的措辞略有不同):

Caused by: 
  java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. 
  Make sure the Cursor is initialized correctly before accessing data from it.
    at android.database.CursorWindow.nativeGetString(Native Method)
    at android.database.CursorWindow.getString(CursorWindow.java:434)
    at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
    at android.database.CursorWrapper.getString(CursorWrapper.java:114)
    at com.twitter.library.media.util.f.a(Twttr:95)
    ...

Caused by: 
  java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow.
  Make sure the Cursor is initialized correctly before accessing data from it.
    at android.database.CursorWindow.nativeGetString(Native Method)
    at android.database.CursorWindow.getString(CursorWindow.java:434)
    at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
    at android.database.CursorWrapper.getString(CursorWrapper.java:114)
    at com.facebook.photos.base.media.MediaItemFactory.b(MediaItemFactory.java:233)
    ...

鉴于在 Facebook 和 Twitter 上分享图片是数百万人整天都在做的事情,我对它如此难以实现感到非常震惊:/

谁能发现我在这里做错了什么?

最佳答案

Twitter(错误地)假设会有一个 MediaStore.MediaColumns.DATA 列。从 KitKat 开始,MediaStore 返回 null,所以幸运的是,Twitter 优雅地处理了 null,并且做了正确的事情。

public class FileProvider extends android.support.v4.content.FileProvider {

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Cursor source = super.query(uri, projection, selection, selectionArgs, sortOrder);

        String[] columnNames = source.getColumnNames();
        String[] newColumnNames = columnNamesWithData(columnNames);
        MatrixCursor cursor = new MatrixCursor(newColumnNames, source.getCount());

        source.moveToPosition(-1);
        while (source.moveToNext()) {
            MatrixCursor.RowBuilder row = cursor.newRow();
            for (int i = 0; i < columnNames.length; i++) {
                row.add(source.getString(i));
            }
        }

        return cursor;
    }

    private String[] columnNamesWithData(String[] columnNames) {
        for (String columnName : columnNames)
            if (MediaStore.MediaColumns.DATA.equals(columnName))
                return columnNames;

        String[] newColumnNames = Arrays.copyOf(columnNames, columnNames.length + 1);
        newColumnNames[columnNames.length] = MediaStore.MediaColumns.DATA;
        return newColumnNames;
    }
}

关于android - 图像共享 Intent 适用于 Gmail,但会导致 FB 和 twitter 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24195674/

相关文章:

android - ListView 没有膨胀

android - 重复构建失败 "To use Coroutine features, you must add ` ktx`......"

android - 无法共享文件需要导出提供程序或 grantUriPermission()

从输出文件夹共享调试 APK 时 Android 应用程序崩溃

android - 带 Kotlin 协程的 NetworkBoundResource

android - 如何测试 android 应用程序的网络错误?

Java嵌套parcelable,无法初始化数组

java - 每次点击后 Activity 都会自行打开

来自通知栏 Intent 的 Android 调用方法

android - 如何模仿选择器 Activity/共享菜单?