本文翻译自android官方文档,结合自己测试,整理如下。
content provider管理数据的访问,我们可以在自己的应用程序中实现一个或多个自定义的provider(通过继承抽象类ContentProvider),当然这些provider需要在manifest文件中注册。尽管content provider是用来为其它程序来访问数据的,但是在自己程序中的activities显然可以对这些数据进行处理。
创建provider之前注意事项
确定是否需要提供content provider。若有以下一种或多种需求的话需要创建content provider:
- 想提供给其他程序复杂的数据或文件;
- 想允许用户将复杂的数据从我们的程序复制到另外的程序中;
- 想使用查询框架提供自定义查询建议。
若在程序内部使用SQLite数据库,则不需要provider。
接下来,通过下列步骤创建provider(先简单的总结,后续详细介绍):
为数据设计存储方式,content provider提供两种方式:
- 文件数据
数据保存在文件中,例如图片,视频,音频等。这些文件存储在私有的空间,provider可以提供外部程序访问。 - 结构化的数据
这样的数据通常保存在数据库,数组,或者相似的结构中,当然可以把这些数据以兼容的方式保存在表中。表中的一行表示一个实体(记录),一列表示实体相关属性的取值。通常这些数据保存在SQLite数据库中,当然也可以采用其他永久保存数据的方式。
- 文件数据
需要继承抽象类ContentProvider,并且覆盖必要的方法。这个类是我们的数据和其他程序交互的接口。
- 定义provider的权限(authority),内容URIs和列名。若程序想要处理intents,则还必须定义intent的action,extra data和flags。同样需要定义其它程序想要访问该provider必须请求的许可(permission)。通常可以考虑把这些值定义为常量并定义在另一个类中。
- 添加额外的信息。
下面详细讲解以上步骤。
设计数据存储
在提供provider之前,我们必须要确定我们的数据该如何存储,当然存储方式我们可以任意指定,然后再针对该存储方式设计provider。
有下列几种存储方式:
- 存储在SQLite数据库中。
- 存储在文件中。
- 存储在网络中。
这一部分可以参考我翻译的文章:Android数据存储方案
注意事项
- 表数据通常需要主键,provider为每行赋值一个唯一的数值。尽管主键这一列可以任意名称,但是推荐使用
BaseColumns._ID
,这样的话,在ListView就能很方便的检索。 - 若提供位图或者更大的文件数据的话,这些数据会保存在文件中,以间接地方式提供。若是使用这些数据的话,我们应该通知外部应用程序它们应该使用ContentResovler类中的文件方法来获取这些数据,例如
openInputStream(Uri uri)
和openOutputStream(Uri uri)
等方法。 - 存储BLOB数据类型的话大小或结构会发生变化。我们可以使用BLOB实现一个模式独立的表,该类型的表,我们需要定义一个主键,一个MIME类型列,一个或多个BLOB类型的列。在BLOB列中数据的含义是通过MIME类型列中的值表示,这种方式允许在相同的表中存储不同的行类型。
设计内容URIs
内容URI是能够识别provider中数据的URI,包括权限(authority)和路径(path)。权限找到provider,路径找到表或文件。还可以有一个id,能够表示某一行。
设计权限authority
权限用于区分不同程序的provider,一般为了避免冲突,都会采用包名的形式命名。例如包名为:com.example.sywyg
,则该权限就可以为:com.example.sywyg.provider
。可以在AndroidManifest配置文件中的<provider>
标签中设置<android:authority>
标签。
设计路径path
URI是权限加路径的方式来查找指定的表。路径是区分同一程序中表或者其它形式(例如文件)的,可以直接添加在权限后面。例如table1和table2,则形成的URI分别为:com.example.sywyg.provider/table1
和com.example.sywyg.provider/table2
。
最后内容URI需要在权限和路径前加上content://
表示内容URI。例如,一个标准的内容URI写法如下:content://com.example.sywyg.provider/table1
。