要创建一个content provider你应该:
继承ContentProvider类
要实现6个ContentProvider类中声明的抽象方法:query() 、insert() 、update() 、delete() 、getType() 、onCreate() 。
query() 方法必须返回一个可以遍历请求的数据的Cursor对象。Cursor本身是个接口,但是Android提供了一些你可使用的现成的Cursor对象。比如说,SQLiteCursor可以在SQLite数据库中存储的数据上迭代。你可以通过SQLiteDatabase类的query()方法获得该Cursor。还有其他的Cursor实现—如为没有存储在数据库中的数据准备的MatrixCursor。
因为这些ContentProvider方法可以在不同的进程和线程中使用各种ContentResolver对象调用,所以它们必须被实现为线程安全的。
当要数据改变时,你也许同样会调用ContentResolver.notifyChange()来通知listener。
在定义子类之后,还有其它的步骤:
public static final Uri CONTENT_URI = Uri.parse("content://com.example.codelab.transportationprovider");
如果这个provider还有子表,也要为每个子表定义CONTENT_URI常量。这些常量必须有相同的authority,只有path不同,比如:
content://com.example.codelab.transportationprovider/train
content://com.example.codelab.transportationprovider/air/domestic
content://com.example.codelab.transportationprovider/air/international
确保要提供一个整型的列,列名为"_id
"(常量为_ID)作为记录的ID。必须有这个字段。如果你使用SQLite数据库,_ID应该是下面的类型:
INTEGER PRIMARY KEY AUTOINCREMENT
AUTOINCREMENT是可选的,但是没有它,SQLIte增加一个ID计数器字段来记录最大记录数的下一个值(?)。如果你删除了最后的一行,添加的下一行将会与删除的一行有相同的ID。AUTOINCREMENT
可以让SQLite来处理ID的增长。
对单个记录: vnd.android.cursor.item/vnd.
yourcompanyname.contenttype
例如:请求列车记录122有这样的URI:content://com.example.transportationprovider/trains/122
会返回这个MIME类型:vnd.android.cursor.item/vnd.example.rail
对多个记录:vnd.android.cursor.dir/vnd.yourcompanyname.contenttype
例如:所有列车的请求URI:content://com.example.transportationprovider/trains
会返回这个MIME类型:vnd.android.cursor.dir/vnd.example.rail
_data
"来列出设备上那个文件的路径。这个字段不打算由用户读取,而是供ContentReslover使用。用户只要在user-facing 的字段调用 ContentResolver.openInputStream()方法。ContentResolver会请求"_data
"字段获得那条记录。因为它有比用户高的权限,所以它可以直接访问文件并为用户返回读取的结果。
声明content provider
要让Android系统知道你开发的content provider,你应该在AndroidManifest.xml文件中用 <provider> 元素声明。未声明的content provider不可用。
<provider>元素的name属性是ContentProvider子类的全名。authorities
属性是标识provider的URI中的authority部分。比如,ContentProvider子类如果是AutoInfoProvider,<provider> 元素或许如下:
<provider android:name="com.example.autos.AutoInfoProvider" android:authorities="com.example.autos.autoinfoprovider" . . . /> </provider>
注意authorities
属性省略了content:URI的path部分。比如说,如果AutoInfoProvider控制着不同类型汽车或不同生产厂商的表格:
content://com.example.autos.autoinfoprovider/honda
content://com.example.autos.autoinfoprovider/gm/compact
content://com.example.autos.autoinfoprovider/gm/suv
它们的path不会在manifest中声明。Authority标识这个provider,而不是path;你的provider可以以你选的的任何方式来解释(interpret)URI的path部分。
其他的< provider
>属性可以设置读写数据的权限,为其提供一个图标或者文本来显示给用户,使provider可用或不可用等等。如果数据不需要在多个运行版本的content provider同步,将multiprocess
属性设置为"true
"。这会允许在每个客户端进程创建一个provider的实例,消除了执行IPC的需要。(IPC:进程间通信)
这里是一个content URI的重要部分的概括:
A. 标准的前缀,指示数据由content provider控制。它永远不会被修改
B. URI的authority 部分,它标识这个content provider。对于第三方应用程序,这一部分应该是一个fully-qualified类名(小写)来确保唯一。Authority在< provider >元素的authorities 属性声明。
<provider android:name=".TransportationProvider" android:authorities="com.example.transportationprovider" . . . >