在Android上通过ContentProvider共享应用程序数据目录中的图像

5
我正在尝试通过ContentProvider公开位于应用程序/data目录中的.png文件,但是不是到达openFile方法而是调用了query方法。现在我只有一张图片需要共享给其他应用程序,如何设置我的Intent以使其前往openFile而不是query?
Intent shareImageIntent = new Intent(Intent.ACTION_SEND);

            shareImageIntent.setType("image/*");

            shareImageIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
            startActivity(Intent.createChooser(shareImageIntent, "Share image"));

URI的格式如下:

content://my.package.contentprovider/fileName

还是需要为此创建一个数据库并返回游标吗?

更新

所以这在除了短信应用程序(这是我决定先测试的)之外的所有应用程序上都可以工作,但是我希望也支持共享到短信应用程序。

以下是相关的堆栈跟踪:

由:java.lang.IllegalArgumentException引起:查询 content://mypackage.myprovider/someImage.png 返回null结果。在 com.android.mms.ui.UriImage.initFromContentUri(UriImage.java:104) 中的 com.android.mms.ui.UriImage。在 com.android.mms.model.ImageModel.initModelFromUri(ImageModel.java:83) 中初始化Model。 在com.android.mms.model.ImageModel.(ImageModel.java:65)中。在 com.android.mms.data.WorkingMessage.changeMedia(WorkingMessage.java:481) 中更改媒体。 在 com.android.mms.data.WorkingMessage.setAttachment(WorkingMessage.java:375) ...

因此,短信应用程序执行的是查询,而不是像我手机上的所有其他应用程序(包括其他 Google 应用程序)一样直接从 openFile读取。

有人知道我需要在此返回什么才能正确执行查询吗?我现在要去挖掘 AOSP 了。

3个回答

4

浏览短信(实际上是彩信)应用程序的源代码后,我得到了以下结果。

UriImage.initFromContentUri内部,应用程序生成查询代码,并假定Cursor中有2个返回的列。

 } else {
   filePath = c.getString(c.getColumnIndexOrThrow(Images.Media.DATA));
   mContentType = c.getString(c.getColumnIndexOrThrow(Images.Media.MIME_TYPE));
 }

因此,为了使您的ContentProvider与MMS应用程序配合使用,您需要在query中返回一个只有一行和两列(Images.Media.DATA和Images.Media.MIME_TYPE)带有适当数据的Cursor。然后,MMS将调用openFile实际检索图像。


请注意,短信应用程序需要填写列,而不是请求它们。 - Snicolas

2
更简单的分享图片资源的方法是将其保存到外部存储器(SD卡),然后执行以下操作:
Uri imageUri = Uri.fromFile(pathToFile);

更新:
尝试使用
Uri imageUri = Uri.parse("android.resource://com.package.yourapp/" +imageResID);

更新2

尝试将文件保存到媒体库中,然后发送它:

String url = Media.insertImage(context.getContentResolver(), imageFile.getAbsolutePath(), imageFile.getName(), imageFile.getName());

Uri imageUri = Uri.parse(url);

最终更新:使用ContentProviderCursor

您的ContentProvider必须实现query(..)方法,并且必须返回一个Cursor。请参见 UrlImage.initFromContentUri(..)的源代码(这是MMS应用程序内部使用的)以查看如何调用光标。如果适合您的需求,请查看MatrixCursor


我特别想访问我的内部存储器。默认情况下,我使用外部存储器,但如果不可用,我需要一个备用方案。 - smith324
看一下这个:http://stackoverflow.com/questions/7175498/why-doesnt-this-code-attach-an-image-to-mms-message - Peter Knego
如果用户没有SD卡怎么办?虽然很奇怪,但这是有可能的。 - Francisco Jordano
@Francisco 这就是我想要解决的问题(不仅仅是SD卡,还包括外部存储设备)。@Peter 那个问题涉及应用程序资源中的内容,我的图像是动态创建的,然后保存到本地目录中。 - smith324
是的,正确。尝试通过保存文件到媒体存储来解决问题。 - Peter Knego
@Peter,请看一下我的更新,除了短信应用程序之外,我所做的似乎对所有东西都有效。 - smith324

0

如果您的内容提供者已经在工作,您可以通过内容提供者中的 openFileDescriptor方法访问ParcelFileDescriptor。

这是一个快速而简单的示例:

ParcelFileDescriptor descriptor = mContext.getContentResolver().openFileDescriptor(IMGURI, "r");
Bitmap bmp = BitmapFactory.decodeFileDescriptor(descriptor.getFileDescriptor());

干杯!


是的,我的ContentResolver正常工作,问题在于短信应用程序没有正确使用它。请查看我的更新。 - smith324

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