创建一个Content Provider

要创建一个content provider你应该:

  • 建立一个存储数据的系统。多数的content providerAndroid的文件存储方法或SQlite数据库来存储数据,但是你可以用任何你想用的方法存储。Android提供了SQLiteOpenHelper类来帮助你创建一个数据库以及SQLiteDatabase来管理它。
  • 继承ContentProvider类来提供对数据的访问
  • manifest文件(AndroidManifest.xml)中为你的应用程序声明这个content provider

继承ContentProvider

要实现6ContentProvider类中声明的抽象方法: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。这是一个代表你的content provider持有的全content:URI字符串,你必须给其定义一个唯一的值。最好的方法是使用content providerfully-qualified类名(小写)。比如,一个TransportationProvider类的URI可以这样定义:

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

  • 定义content provider将要返回给用户的列的名字。如果你使用了底层的数据库,这些列名通常与SQL数据库列名相同。同样是声明为public static字符串常量,用户可以使用它们来指明要查询的列。

确保要提供一个整型的列,列名为"_id"(常量为_ID)作为记录的ID。必须有这个字段。如果你使用SQLite数据库,_ID应该是下面的类型:

INTEGER PRIMARY KEY AUTOINCREMENT

AUTOINCREMENT是可选的,但是没有它,SQLIte增加一个ID计数器字段来记录最大记录数的下一个值(?)。如果你删除了最后的一行,添加的下一行将会与删除的一行有相同的IDAUTOINCREMENT可以让SQLite来处理ID的增长。

  • 备注好列的每一种数据类型,用户需要它来读取数据。
  • 如果你要处理一个新的数据类型,你必须声明一个新的MIME类型来作为你实现ContentProvider.getType()的返回。这个类型部分取决于提交给getType()content:URI是否限制对具体记录的请求。对单个记录有一种形式,对多个记录又有另一种形式。用Uri的方法来确定什么将被请求。下面是每种类型的一般格式:

对单个记录: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

  • 如果你要公布因太大而不能放入表里的二进制数据,公布(expose)给用户的数据的的字段应该包含content:URI字符串。这是让用户可以利用数据文件的字段。这个记录也应该有另一个字段,名为_data"来列出设备上那个文件的路径。这个字段不打算由用户读取,而是供ContentReslover使用。用户只要在user-facing 的字段调用

ContentResolver.openInputStream()方法。ContentResolver会请求"_data"字段获得那条记录。因为它有比用户高的权限,所以它可以直接访问文件并为用户返回读取的结果。

声明content provider

要让Android系统知道你开发的content provider,你应该在AndroidManifest.xml文件中用<provider>元素声明。未声明的content provider不可用。

<provider>元素name属性是ContentProvider子类的全名。authorities属性是标识providerURI中的authority部分。比如,ContentProvider子类如果是AutoInfoProvider<provider>元素或许如下:

<provider android:name="com.example.autos.AutoInfoProvider" android:authorities="com.example.autos.autoinfoprovider" . . . /> </provider>

注意authorities属性省略了content:URIpath部分。比如说,如果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可以以你选的的任何方式来解释(interpretURIpath部分

其他的< provider >属性可以设置读写数据的权限,为其提供一个图标或者文本来显示给用户,使provider可用或不可用等等。如果数据不需要在多个运行版本的content provider同步,multiprocess属性设置为"true"。这会允许在每个客户端进程创建一个provider的实例,消除了执行IPC的需要。(IPC:进程间通信)

Content URI 总结:

这里是一个content URI的重要部分的概括:

A. 标准的前缀,指示数据由content provider控制。它永远不会被修改

B. URIauthority部分,它标识这个content provider。对于第三方应用程序,这一部分应该是一个fully-qualified类名(小写)来确保唯一。Authority< provider >元素的authorities属性声明。

<provider android:name=".TransportationProvider" android:authorities="com.example.transportationprovider" . . . >


更多相关文章

  1. android开发数据存储方式
  2. Android下使用camera2和Surfaceview预览图像并取得YUV420p数据回
  3. 通过Android 客户端上传数据到服务器
  4. 通过adb工具查看android sqlite3数据库
  5. Android实习生 —— 网络请求及数据解析
  6. Android P的Socket通信实现之传输图片数据
  7. Android数据存储的方法

随机推荐

  1. android 根据TextView宽度 自动缩小字体
  2. android > APK更新
  3. Compile Busybox for Android
  4. android spinner 选中后显示字体的颜色设
  5. android window.requestWindowFeature()
  6. android webview 中网页数据与js交互
  7. java.lang.NullPointerException Attempt
  8. Android(安卓)Studio 用 JNI 实现与原生
  9. android蓝牙模块
  10. CheckBox android:paddingLeft 不兼容问