内容提供者原理和简单使用

为什么要有内容提供者内容提供者技术的目的是:把私有数据库的数据的内容暴露给外部使用;

我们知道,微信、QQ等应用都可以读取手机中联系人和短信的数据。而联系人和短信都是系统内置的应用,它们的数据都存储在相应的数据库中。

在com.android.provider.telephony/databases/mmssms.db就是短信的数据库,通过下面的图可以知道mmssms.db的权限为-rw-rw—,也就是其他用户不可以直接访问,是私有的。

同样的com.android.provider.contacts/databases/contact2.db是联系人的数据库,同样也是私有的权限。

既然它们都是私有的,但是又有需求获取里面的数据应该怎么办?Google提供者了内容提供者的技术,就可以解决这一需求。

内容提供者的工作原理

由于数据库是私有的,外部应用不可以直接访问。那么便在应用内部使用内容提供者,向外部暴露接口,这样外部可以借助“中间人”访问到内部的数据库,原理图如下:

内容提供者的编写步骤如下:①创建数据库、表,因为内容提供者主要是把私有数据库数据提供给外部访问。②写一个类继承ContentProvider类,并重写其中的onCreate()、query()、insert()、update()、delete()、getType()等方法。③确定主机名(authority),添加路径匹配规则,此处会利使用到UriMatcher类。④在清单文件中声明内容提供者,并添加关键属性android:authorities⑤编写内容提供者的onCreate()、query()、insert()、update()、delete() 等方法。

接下来就一步一步把所有步骤说清。

第一步,创建数据库、表。很简单写一个继承SQliteOpenHelper得类,并创建数据库。代码如下:

{public MySQLiteOpenHelper(Context context) {super(context, “account.db”, null, 1);}(SQLiteDatabase db) {// 创建数据库,并初始化两条语句db.execSQL(“create table account (_id integer primary key autoincrement,name varchar(20),money varchar(20))”);db.execSQL(“insert into account (‘name’,’money’) values (‘张三’,’2000′)”);db.execSQL(“insert into account (‘name’,’money’) values (‘李四’,’5000′)”);}(SQLiteDatabase db, int oldVersion, int newVersion) { }}

第二步,写一个类继承ContentProvider类,并重写其中方法。主要都是一些骨架的代码,也没什么难度。

{() {return true;}Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {return null;}Uri insert(Uri uri, ContentValues values) {return null;}(Uri uri, String selection, String[] selectionArgs) {return 0;}(Uri uri, ContentValues values, String selection, String[] selectionArgs) {return 0;}@Overridepublic String getType(Uri uri) {;}}

第三步,,从第三步开始就比较关键了。要确定主机名(authority),添加路径匹配规则,此处是使用内容解析者时,调用其他应用私有数据库所使用的。代码如下,对了这些代码是写在内容提供者类中的:

QUERY_SUCCESS = 0;UPDATE_SUCCESS = 1;DELETE_SUCCESS = 2;INSERT_SUCCESS = 3;UriMatcher MURI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);// 添加路径匹配规则static {MURI_MATCHER.addURI(“com.bzh.account.contentprovider”, “insert”, INSERT_SUCCESS);MURI_MATCHER.addURI(“com.bzh.account.contentprovider”, “delete”, DELETE_SUCCESS);MURI_MATCHER.addURI(“com.bzh.account.contentprovider”, “update”, UPDATE_SUCCESS);MURI_MATCHER.addURI(“com.bzh.account.contentprovider”, “query”, QUERY_SUCCESS);}

第四步,内容提供者是四大组件之一,四大组件都需要在清单文件中声明。在清单文件中声明内容提供者,并添加关键属性android:authorities,这个属性的内容和添加路径匹配规则addURI()的第一个参数必须一致。代码如下:

<provider >

第五步,编写内容提供者的onCreate()、query()、insert()、update()、delete() 等方法。这些方法的内容都是使用SQLiteDatabase内部的方法直接调用,也比较简单。

private SQLiteDatabase db;String ACCOUNT = “account”;() {MySQLiteOpenHelper mySQLiteOpenHelper = new MySQLiteOpenHelper(getContext());db = mySQLiteOpenHelper.getWritableDatabase();return true;}Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {int MATCH_CODE = MURI_MATCHER.match(uri);// 判断路径是否匹配成功if (MATCH_CODE == QUERY_SUCCESS) {// 调用SQLiteDatabase中的方法查询私有的数据库return db.query(ACCOUNT, projection, selection, selectionArgs, null, null, null);}return null;}Uri insert(Uri uri, ContentValues values) {int MATCH_CODE = MURI_MATCHER.match(uri);// 判断路径是否匹配成功if (MATCH_CODE == INSERT_SUCCESS) {long insertResult = db.insert(ACCOUNT, null, values);// 此处的Uri可以随意写return Uri.parse(“com.bzh.account.contentprovider-result:” + insertResult);}return null;}(Uri uri, String selection, String[] selectionArgs) {int MATCH_CODE = MURI_MATCHER.match(uri);// 判断路径是否匹配成功if (MATCH_CODE == DELETE_SUCCESS) {return db.delete(ACCOUNT, selection, selectionArgs);}return 0;}(Uri uri, ContentValues values, String selection, String[] selectionArgs) {int MATCH_CODE = MURI_MATCHER.match(uri);// 判断路径是否匹配成功if (MATCH_CODE == UPDATE_SUCCESS) {return db.update(ACCOUNT, values, selection, selectionArgs);}return 0;}@Overridepublic String getType(Uri uri) {;}

至此,整个内容提供者就编写完毕了,接下就是如何使用了,具体如何使用将在下一节讲述。

使用内容解析者对内容提供者进行增删改查操作

回想一下上面的原理图,访问私有数据库的内容提供者已经准备完毕,家下来是使用内容解析者间接调用数据库内容的时候了。

相对于创建内容提供者而言,使用解析者调用提供者提供的方法就简单很多了。

创建一个工程,并添加几个增删改查的按钮,布局之类的比较简单不贴了,请看图:

接下来要做的事情就是,当点击按钮时调用内容提供者对应的方法。其中最值得注意的是Uri.parse()内容的写法。

Uri uri = Uri.parse(“content://com.bzh.account.contentprovider/query”);其实你已经错过了旅行的意义。

内容提供者原理和简单使用

相关文章:

你感兴趣的文章:

标签云: