简介
Content provider管理android以结构化方式存放的数据。他以相对安全的方式封装数据并且提供简易的处理机制。Content provider提供不同进程间数据交互的标准化接口。
当你准备取出content provider中的数据时,你需要获得一个和当前上下文相关的ContentResolver对象作为客户端。这个对象和一个继承至ContentProvider的provider对象相关联。provider从客户端接收请求并且返回结果。
如果你不准备和其他应用共享你的数据,你不需要自定义provider。但是,你需要实现provider以满足个性化搜索数据的需求。同时,当你拷贝和粘贴复杂数据或者文件到他人应用中时,也需要provider。
当你准备取出content provider中的数据时,你需要获得一个和当前上下文相关的ContentResolver对象作为客户端。这个对象和一个继承至ContentProvider的provider对象相关联。provider从客户端接收请求并且返回结果。
如果你不准备和其他应用共享你的数据,你不需要自定义provider。但是,你需要实现provider以满足个性化搜索数据的需求。同时,当你拷贝和粘贴复杂数据或者文件到他人应用中时,也需要provider。
延伸阅读:
继承关系
当使用它时,需要实现如下方法:
onCreate()
初始化 providerquery(Uri, String[], String, String[], String)
返回数据给调用者insert(Uri, ContentValues)
在 content provider中插入新的数据update(Uri, ContentValues, String, String[])
更新在content provider存在的数据delete(Uri, String, String[])
在content provider中删除数据getType(Uri)
返回一个MIME类型的数据数据操作型方法可以在多线程中调用,并且是线程安全的。其他方法只在application的主线程中调用,并且要避免耗时操作。尽管必须实现这些方法,但你的代码没有做任何事情,除了返回预期的数据类型
什么情况下使用content provider
- 提供复杂的数据或文件给其它应用程序
- 允许使用者复制复杂的数据到其它app
- 提供在搜索协议框架下的自定义搜索
建立provider
- 为你的数据设计存储结构【文件类型||结构体类型】
- 实现一个继承自ContentProvider的类和必要方法。此类作为数据与安卓系统之间的接口
- 定义一个String【content URI】,它包含其内容的uri和列名。如果您希望供应商的应用程序来处理intents,还定义intents的actions, extras data, and flags.还需要声明权限。为此,应该用一个类来承载这些值
如何设计数据存储
content provider是一个存储结构化数据的接口,在创建接口它之前,你需要决定如何存储数据,你可以将数据存储为任何你想要的形式,还可以为其设计读写接口。
在安卓上可用的数据存储技术:SQLite、file
几点建议:
表格数据应该有主键(
primary key
)
如果需要存储图片或其他十分大的文件,将它的路径存入表中
用
Binary Large OBject (BLOB)
存储不同大小或结构的数据,例如
protocol
或json
设计content URI
content://<authority>/<path>/<id>
content uri用于鉴别provider中的数据,它包括provider的名称和表名(文件名),可选的id部分指向表中单独的一行。在ContentProvider中的所有的数据访问函数都需要content uri作为参数,以便于确定访问的表、行、或者文件。
- 所有者名称(authority):为避免冲突,命名规则遵循包名的命名规则,
com.example.<appname>.provider
.
- 路径名(path):
com.example.<appname>.provider/table1
andcom.example.<appname>.provider/table2
.
- ID:加在uri的末尾
content://com.example.app.provider/table3/1
实现ContentProvider
该ContentProvider的实例,管理结构化数据集,通过
其他应用程序的处理请求。所有的访问形式最终都需要调用
ContentResolver,
然后调用的ContentProvider的具体方法来获取许可。
需覆盖开头所说的几个方法
实现query()
- 必须返回一个游标对象(Cursor )或者抛出错误。
- 使用了数据库存储数据,那么会很轻松的返回游标对象。
- 查询结果为空也应该返回游标,同时在
getCount()
中应该返回0。
- 在查询过程中发生内部错误,返回null。
- 如果不是使用数据库,使用一个Cursor的子类
实现insert()
- 该方法主要用于向表中插入数据, 值由参数
ContentValues
提供。如果列名没有指定相应的值,则应该提供一个默认值。
- 该方法返回一个content URI,该uri指向新添加的行
实现delete()
- 该方法并没有在物理上删除数据。
- 如果您使用了同步适配器,你应该考虑标记需要删除的行以“删除”标志,而不是真的删除的行。
- 同步适配器可以检查删除的行,并在供应商删除之前从服务器上删除它们。
实现update()
实现onCreate()
安卓主线程直接调用,因此应该在此方法仅执行快速运转的初始化任务,并推迟数据库创建和数据加载,直到提供实际接收的数据的请求。
MIME Types
通过一个content uri来描述数据的类型
一些公共的MIME Types
http://www.iana.org/assignments/media-types/index.htm
构成:
类型:
vnd
亚类型:单行
android.cursor.
item
/
多行
android.cursor.
dir
/
专用部分:
vnd.<name>
.
<type>
name建议用公司名称或者包名,type建议用表名
一个完整的示例
vnd.android.cursor.dir/vnd.com.example.provider.table1
实现承载类
必须声明为
public final
包含URIs, 列名, MIME types, 和其它属于
provider 的元数据
官方示例
ContactsContract
provider标签元素
使用该标签在
manifest
文件中声明一个provider,该标签包含以下信息
Authority (所有者名称)
Provider class name
Permissions
android:grantUriPermssions
: 临时许可标志android:permission
: 单一provider读/写权限android:readPermission
: Provider读权限android:writePermission
: Provider写权限
启动和控制属性
android:enabled
: Flag 允许系统启动providerandroid:exported
: Flag 允许其他 applications使用此 provider.android:initOrder
: The order in which this provider should be started, relative to other providers in the same process.android:multiProcess
: Flag allowing the system to start the provider in the same process as the calling client.android:process
: 运行provider的进程名称android:syncable
: Flag 该提供者的数据是与一个服务器上的数据进行同步的。
信息属性
android:icon
:一个图标,该图标绘制在Settings > Apps > All的provider上android:label
: 一个label,显示在Settings > Apps > All的provider上
Intents and Data Access
应用程序可以用一个Intent间接访问content provider,
应用程序不调用任何ContentResolver的或ContentProvider的方法。
相反,它会发送一个启动活动的intent,这往往是应用程序自己的provider。目标activity负责在ui上检索和显示数据。取决于在action中的intent,目标activity也可以提示用户更改provider提供的数据。在intent.
extras方法中的数据会显示在ui界面上,用户可在provider修改这些数据之前修改它。