我正在设计一个可以处理复杂对象列表的Android应用程序 . 对象包括伴随一组属性(例如,重要性级别和最后查看时间)的文本或图形数据 . 我想帮助我的应用程序使用复制和粘贴功能,这将遵循3条规则:
-
当用户复制对象然后将其粘贴到我的应用程序时,将添加具有相同属性的对象的完整副本 .
-
当用户复制对象然后将其粘贴到使用新的复制/粘贴API(android.content.ClipboardManager)的其他应用程序时,该应用程序将根据对象所代表的文本或图形数据接收文本或图像 . 如果是图像,该应用程序将以文件路径或媒体库内容URI的形式接收图像 .
-
当用户复制一个对象然后将其粘贴到使用旧式弃用API(android.text.ClipboardManager)的其他应用程序时,该应用程序将只接收由该对象表示的文本 . 如果对象表示图像,则该应用将以文本表示形式接收URI,甚至是空文本 .
到目前为止,我已经研究过Google文档并浏览了各种编程论坛,但没有做到这一点 . 目前我有两个可供选择的邪恶:
1)创建一个与对象一起使用的内容提供者,并将内容URI复制到剪贴板 . 不幸的是,这意味着第三方应用程序,为了检索文本或图像,必须知道我的内容提供商的内部组织,我当然不能假设 .
2)复制到剪贴板只是文本数据(类型为ClipDescription.MIMETYPE_TEXT_PLAIN)或只是图像的URI(类型为ClipDescription.MIMETYPE_TEXT_URILIST) . 在这种情况下,粘贴到我自己的应用程序时,我可以't retain object'属性 .
有任何想法吗?
1 回答
使用
ContentProvider
是正确的做法 . 其他应用程序不需要了解内容的结构或组织:内容URI可以用作不透明标识符,并且(在API 11及更高版本中)一个URI可以有多种类型 .粘贴为文本
如果实现ContentProvider.openTypedAssetFile,则提供程序可以向请求映像的客户端提供映像,将内部数据格式提供给请求特定于供应商的MIME类型的客户端 . 这是_1285333用于从任意内容URI获取文本的机制:它请求类型
text/*
,并将返回的流读取为字符串 . (不要尝试复制无限的文本流!)如果此调用失败,它只会放置URI本身的文本 . 旧版getText
API也使用此coerceToText
函数 . 这会对您的旧版和纯文本客户端进行排序 .粘贴为图像
只需要图像的客户端应该使用与上面相同的机制,这意味着
ContentProvider.openTypedAssetFile
将用于文本,但请求的类型为image/*
. 但我不建议你实现ContentProvider.getType和ContentProvider.getStreamTypes来返回该URI的图像类型(而不是特定于供应商的类型) .实现
query
以返回一个名为(值)MediaStore.Images.ImageColumns.DATA
的列的游标 . 如果要向这些客户端提供元数据,还可以包含MediaStore.Images.ImageColumns
中的其他列 .然后你只需要实现
openFile
来返回图像的文件描述符 . 请务必检查mode
参数,以避免让其他应用程序能够在您的文件中写入 . 你可以调用ParcelFileDescriptor.open来创建你需要从你拥有的路径返回的ParcelFileDescriptor
.粘贴为特定于供应商的对象
所以's all third-party clients for your service dealt with. Now what about pasting into your own app? There'这两件事你可以在这里做 . 正如我在上一节中提到的,您可以使用ContentResolver.openTypedAssetDescriptorFile来请求特定于供应商的类型,并实现
ContentProvider.openTypedAssetFile
以返回该类型的流 . 如果您的特定于应用程序的数据是包含序列化数据等的特殊类型的文件,则此选项非常适合 . 如果您的特定于应用程序的内容是数据库行,那么您可以使用query
:它可以将您喜欢的任何特定于应用程序的数据放入返回的游标,以及上面讨论的MediaStore
列 .这些方法中的任何一种都提供了一种方便的方法来使用
ContentProvider
从存储机制中抽象出前端 . 我在一个应用程序中实现共享时做到了这一点,这是一个非常积极的变化,强加了一个明确的边界,并迫使我清理所有我偷偷摸摸的,封装违反的数据库访问,从而产生一个更易于维护的代码库 . 它还使内置使用更容易支持Loader
s,Adapter
和ContentObserver
以减小前端代码的大小 .但是,这个强制封装边界可能在您的应用程序的错误位置,或者您的粘贴目标需要访问相同的Java对象,而不仅仅是游标或序列化数据 . 在这种情况下,它根本不使用
ContentResolver
.结论
所有这些看起来似乎都是一大堆蠕虫,在某种程度上它是开放的 . 但是
ContentProvider
实际上很容易实现,如果你只想做一件事,一旦你发现其他问题它可以帮你解决 .