为了跨程序访问数据。试想如果在App-1中创建了一个私有数据库,App-2是不能直接访问的。因为权限不够,虽然可以使用chmod 777
来修改权限,然后使用SQLiteDatabase.openDatabase
的静态方法,填上具体的路径和模式来访问。但这并不推荐,有没有更好的办法?官方推荐使用ContentProvider--内容提供者。
简单起见,使用以前的数据库的项目DatabaseTest,同时建立两个表book和category, onUpgrade
方法实现了数据库的升级功能。onUpgrade
里面强制onCreate
,注意必须先删除原来的表,否则我们创建时候发现原来的表还存在就会报错。
MainActivity里面就显示下界面,省略了。
如果想让这个数据库共享,其他应用也能访问?只需新增一个内容提供者即可。
New -> Other -> ContentProvider,AS会帮我们在AndroidManifest.xml里注册好。有一个属性authorities
比较重要,一般命名方式是<包名>.provider
,比如com.example.cptest.provider
。
可以看到,内容提供者的方法和操作数据库差不多。最大的不同是操作数据库需要填上表名,而内容提供者中的方法需要填上Uri。为什么呢?因为是跨程序访问数据,多个应用的表名可能一样,这样就不知道到底访问哪个应用的数据了。Uri的格式一般如下
content://<package_name>.provider/<path>/<id>
,举个例子content://com.example.databasetest.provider/book/2
表示访问book表的id为2的那行数据。
甚至可以使用通配符
于是可以匹配任意表的URI可以写成content://com.example.databasetest.provider/*
可以匹配一个表中任意一行的URI可以写成content://com.example.databasetest.provider/book/#
流程是这样的,一旦需要内容提供者时就会调用其onCreate方法并且实例化了数据库连接帮助类。提供了UriMatcher,在静态代码块里初始化,添加上我们期望匹配的URI
接收三个参数,分别是authority、path和自定义唯一码。
增删改查的方法就不说了,注意两点。
最后介绍getType()
这个方法 -- 根据传入的内同URI来返回相应的MIME类型。
对于content://com.example.databasetest.provider/book
这个URI,对应的MIME是vnd.android.cursor.dir/vnd.com.example.databasetest.book
;
对于content://com.example.databasetest.provider/book/2
这个URI,对应的MIME是vnd.android.cursor.item/vnd.com.example.databasetest.book
。
好了内容提供者写好了,赶紧在另外一个应用里尝试一下!
假设此应用时App-B,上面的应用是App-A。
布局实现对上述应用数据库中的book表的CURD
MainActivity,所有的方法都是基于getContentResolver()
。得到内容提供者后,尝试访问App-A的数据。此时App-A里内容提供者的onCreate
方法得到执行,由此创建了数据库。
我们只需正确匹配Uri就能访问到App-A中的数据库了,代码很简单,不需要讲解了。
是不是很方便?使用ContentProvider就能式样App-A轻松访问到App-B中的内容。还有一些常见的例子,比如访问联系人和短信数据等。