一、写在前面
一直很好奇系统是如何通过"content://xxx.xxx.xxx"来访问归属地数据库的,通过研究代码和API参考文档以及网络上的资料基本上弄明白了,于是有了以下的内容。
二、Android Content Provider介绍
在Android系统中Content Provider用于数据的存储和获取,所有的APP都可以通过Content Provider来读写数据。
Content Provider其实是对数据存储的访问方式的封装,让开发者可以通过统一的方式去读取不同的数据(在Android上,数据主要是以SQLite数据库形式存储),
而且不必掌握繁琐的SQL语法。同时能够很好地控制访问权限(读/写)。
Content Provider是APP之间唯一可以共享数据的方式。
在SDK中的android.provider里面你会发现很多Content Provider,比如:多媒体、联系人、通话记录等。
我们可以通过ContentResolver来读写数据,这里不做详细介绍,有兴趣可以自行阅读相关API参考文档
三、Content Provider的组成
其实Android有四大组件的说法:Activity、Service、Broadcast Receiver还有就是Content Provider!
我们一般编写APP都是基于Activity的,其实一个APP里面是可以没有Activity的!比如Android手机上都有的一个APP:Contact Provider(联系人存储)
所以我们完全可以自己新建一个APP来添加Content Provider。
先想想Provider应该具备那些组成部分?
1. 既然是对数据存储的管理和读写,那么肯定要有数据存储。一般来说可以是SQLite数据库文件
2. 必须提供访问接口:继承抽象类 ContentProvider。
3. 要让其他APP可以访问,就需要在AndroidManifest.xml里声明
四、添加Content Provider
创建数据存储
理论上讲,我们可以以任何形式来存储数据,比如二进制文件、xml或者SQLite数据库。
在Android系统中sqlite是首选,因为sqlite设计初衷就是应用于嵌入式等平台的轻量级文本数据库,它具备大多数关系数据库所具备的功能。
如果要使用sqlite数据库,Android SDK提供了android.database.sqlite.SQLiteOpenHelper工具类,使用SQLiteOpenHelper可以很方便地创建和更新sqlite数据库。
public class AutoInfoProvider extends SQLiteOpenHelper {
/*
构造函数
context 用于打开或者创建数据库的上下文
name 数据库文件名,如果为null则表示创建一个内存数据库
factory 用于创建cursor,为null时调用默认的CursorFactory
version 数据库的版本号,从1开始,如果数据库的版本较低会调用 onUpgrade(SQLiteDatabase, int, int)来更新数据库,
如果版本较高会调用 onDowngrade(SQLiteDatabase, int, int) 来降级数据库
*/
public AutoInfoProvider(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
/*
当数据库被创建是被调用,可以在这里执行一些数据库初始化的操作,比如创建各个表以及导入初始数据等
*/
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
}
/*
当数据库需要升级版本的时候调用
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
这样我们可以用DemoSQLiteOpenHelper来打开数据库文件,并且在第一次打开的时候可以对数据库进行创建和初始化。
实现ContentProvider接口
android.content.ContentProvider严格来说是一个抽象类,我们需要通过继承它来实现自己的Content provider。有以下方法需要实现:
onCreate() 当Content Provider初始化时调用
query(Uri, String[], String, String[], String) 用于查询数据,返回一个cursor
insert(Uri, ContentValues) 插入数据
update(Uri, ContentValues, String, String[]) 更新数据
delete(Uri, String, String[]) 删除数据
getType(Uri) 返回数据的MIME类型
" insert、update、delete等方法需要考虑线程同步的问题,因为有可能多个线程同时条用这些方法来修改数据库,而SQLite是不支持多线程同时写入的。"
在AndroidManifest.xml声明新建的Provider
我们必须在AndroidManifest.xml里面声明Provider,否则是该Provider是无法被访问使用的!
<provider android:name="com.example.autos.AutoInfoProvider"
android:authorities="com.example.autos.autoinfoprovider"
. . . />
</provider>