Provider数据类型
Contentproviders能识别多种不同的数据类型.用户词典只识别文本类型,但其它provider可以识别下列格式:
整型
长整型(long)
浮点
长浮点(double)
另一个provider经常使用的数据类型是"大二进对象"(BLOB) ,它就像一个64KB的字节数组.你可以通过Cursor类的"get"方法查看可用的数据类型.
provider中的每列的数据类型都是在它们的文当中列出.用户词典Provider的各数据类型在它的契约类UserDictionary.Words(契约类在ContractClasses一节中讲解)的参考文档中列出.你也可以调用Cursor.getType()来确定数据类型.
Provider还为每个contentURI维护着MIME数据类型信息.你可以用MIME信息来确定你的应用是否能处理provider提供的信息,或基于MIME信息去选择一个要处理的数据类型.当你使用包含复杂数据结构或文件的provider时,你经常需要MIME信息.例如,联系人Provider中的表ContactsContract.Data用MIME类型来标志所存储的联系人数据的每行类据.要获得一个contentURI的MIME类型,需调用ContentResolver.getType().
Thesection MIME类型参考一节描述了标准的和自定义的MIME类型语法.
操作Provider的三种型式
在应用开发中,有三种很重要的操作provider的型式:
Batchaccess:你可以使用ContentProviderOperation类的方法创建一批操作调用,然后使用ContentResolver.applyBatch()应用它们.
Asynchronousqueries: 你需要在另一个线程中执行请求.这样做的一个办法使用一个CursorLoader对象.在Loaders指南中的例子演示了如何做.
Dataaccess via intents:尽管你不能直接向一个provider发送intent,但你可以向provider的应用发送intent,这通常是修改provider'的数据的最佳方法.
通过intent批量操作和修改的方法在下面的章节中讲解.
批操作
对一个provider的批操作在插入很大数量的行时很有用,也可以用于在一个方法调用中向多个表中插入多行,或用于将一系列操作作为一个事物执行时(一个原子操作).
要在"批模式"下操作一个provider,你需创建一个ContentProviderOperation对象的数组然后使用ContentResolver.applyBatch()把它派送到一个contentprovider.你应把contentprovider的authority而不是一般的contentURI传给这个方法,authority允许数组中的每一个ContentProviderOperation对象作用于不同的表.对ContentResolver.applyBatch()的调用会返回一个数组存放结果.
契约类ContactsContract.RawContacts的描述中包含一个代码片段演示了批插入.ContactManager应用例子包含了一个批操作的例子,在它的ContactAdder.java源码文件中.
使用其它应用显示数据
如果你的应用拥于操作权限,但你可能仍想使用一个intent在其它应用中显示数据.例如,日历应用接受一个ACTION_VIEWintent,然后显示一个日期或事件.这使你可以显示一个日期信息但不用自己创建界面.更多知识,请看CalendarProvider指南.
你发送intent的目标应用不一定必须是与provider相关连的应用.例如,你可以从联系人Provider获取一个联系人,然后发送一个包含了联系人图像的contentURI的ACTION_VIEWintent到一个图像显示应用.
通过intent操作数据
Intents可以提供间接操作contentprovider的功能.于是你的应用可以操作不具有权限的provider中的数据.这既可以通过从有权限的应用中获取一个返回的intent实现,也可以通过激活一个具有权限的应用来让用户操作方式来实现.
使用临时权限操作
即使你不具有合适的权限,你还是可以操作contentprovider中的数据的,只需把一个intent发送给一个具有权限的应用然后获得一个返回的包含"URI"权限的intent即可.获得的特定的URI的权限会一直持续到获取它们的activity结束.那些具有权限的应用通过在要返回的intent中设置一个标志来赋与临时权限:
读权限:FLAG_GRANT_READ_URI_PERMISSION
写权限:FLAG_GRANT_WRITE_URI_PERMISSION
注:这些标志不会给于对contentURI中包含的authority对应的provider的读写权限.操作仅仅针对URI本身.
一个provider在它的manifest中定义contentURI们的URI权限,使用<provider>元素的android:grantUriPermission属性和<provider>子元素的<grant-uri-permission>属性.URI权限机制在Securityand Permissions指南中的"URI权限"一节中做了详细的描述.
例如,你可以从ContactsProvider中取得一个联系人数据,即使你不具有READ_CONTACTS权限.你可能想在一个在某人生日时向他发送电子贺卡的应用中这样做.你首选的是让用户仅控制你的应用使用的联系人们,而不是直接请READ_CONTACTS权限以操作所有的联系人和他们所有的信息.要这样做,需执行以下过程:
你的应用发送一个intent,它包含了actionACTION_PICK和"contacts"MIME 类型CONTENT_ITEM_TYPE,使用方法startActivityForResult().
因为这个intent匹配了Peopleapp的"selection" activity,activity将被置于前台.
在selectionactivity中,用户选择一个contact来更新.当这样做时,selectionactivity调用setResult(resultcode,intent)来创建一个intent返回给你的应用.Intent中包含了用户选择的联系人的contentURI和"extras"标志FLAG_GRANT_READ_URI_PERMISSION.这个标志赋与你的应用URI权限以从URI指定的联系人中读取数据.这个selectionactivity之后调用finish()将控制返回给你的应用.
你的activity返回到前台,并且系统调用你的activity的onActivityResult()方法.这个方法接收被Peopleapp中的selectionactivity 创建并返回的intent.
使用返回的intent中的contentURI,你可以从ContactsProvider读contactdata,即使你没有在你的manifest中请求永久性的Provider读权限.然后你就可以获取联系人的生日信息和他的email地址然后给他发送电子贺卡.
使用其它的应用
一个使用户修改你的应用不具有权限的数据的简单方法是激活一个有权限的应用,然后让用户在它正上进程操作.
举个例子,日历应用接收一个ACTION_INSERTintent,使你激活日历应用的插入界面.你可以在这个intent中传递"额外的"数据,应用用它来预置界面.因为返回的事件具有复杂的语法,所以向日历Provider中插入事件的最好的方式就是使用一个ACTION_INSERT激活Calendar应用然后让用户在它上面插入事件.