创建自己的内容提供器
在上一节当中, 我们学习了如何在自己的程序中访问其他应用程序的数据。 总体来说思路还是非常简单的, 只需要获取到该应用程序的内容URI, 然后借助ContentResolver进行CRUD操作就可以了。 可是你有没有想过, 那些提供外部访问接口的应用程序都是如何实现这种功能的呢?它们又是怎样保证数据的安全性, 使得隐私数据不会泄漏出去? 学习完本节的知识后, 你的疑惑将会被一一解开。
创建内容提供器的步骤
如果想要实现跨程序共享数据的功能, 官方推荐的方式就是使用内容提供器, 可以通过新建一个类去继承ContentProvider 的方式来创建一个自己的内容提供器。 ContentProvider 类中有6个抽象方法, 我们在使用子类继承它的时候, 需要将这6个方法全部重写。 新建MyProvider 继承自ContentProvider , 代码如下所示:
package com.example.administrator.myapplication;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
public class MyProvider extends ContentProvider {
@Override
public boolean onCreate() {
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[]
selectionArgs, String sortOrder) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[]
selectionArgs) {
return 0;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public String getType(Uri uri) {
return null;
}
}Code language: JavaScript (javascript)
在这6个方法中, 相信大多数你都已经非常熟悉了, 我再来简单介绍一下吧。
- onCreate()
初始化内容提供器的时候调用。 通常会在这里完成对数据库的创建和升级等操作, 返回true 表示内容提供器初始化成功, 返回false 则表示失败。 - query()
从内容提供器中查询数据。 使用uri 参数来确定查询哪张表, projection 参数用于确定查询哪些列, selection 和selectionArgs 参数用于约束查询哪些行, sortOrder 参数用于对结果进行排序, 查询的结果存放在Cursor 对象中返回。 - insert()
向内容提供器中添加一条数据。 使用uri 参数来确定要添加到的表, 待添加的数据保存在values 参数中。 添加完成后, 返回一个用于表示这条新记录的URI。 - update()
更新内容提供器中已有的数据。 使用uri 参数来确定更新哪一张表中的数据, 新数据保存在values 参数中, selection 和selectionArgs 参数用于约束更新哪些行, 受影响的行数将作为返回值返回。 - delete()
从内容提供器中删除数据。 使用uri 参数来确定删除哪一张表中的数据, selection 和selectionArgs 参数用于约束删除哪些行, 被删除的行数将作为返回值返回。 - getType()
根据传入的内容URI来返回相应的MIME类型。
可以看到, 几乎每一个方法都会带有Uri 这个参数, 这个参数也正是调用ContentResolver的增删改查方法时传递过来的。 而现在, 我们需要对传入的Uri 参数进行解析, 从中分析出调用方期望访问的表和数据。
回顾一下, 一个标准的内容URI写法是这样的:
content://com.example.app.provider/table1Code language: JavaScript (javascript)
这就表示调用方期望访问的是com.example.app这个应用的table1表中的数据。 除此之外, 我们还可以在这个内容URI的后面加上一个id, 如下所示:
content://com.example.app.provider/table1/1Code language: JavaScript (javascript)
这就表示调用方期望访问的是com.example.app这个应用的table1表中id为1的数据。
内容URI的格式主要就只有以上两种, 以路径结尾就表示期望访问该表中所有的数据, 以id结尾就表示期望访问该表中拥有相应id的数据。 我们可以使用通配符的方式来分别匹配这两种格式的内容URI, 规则如下。
*: 表示匹配任意长度的任意字符。
: 表示匹配任意长度的数字。
所以, 一个能够匹配任意表的内容URI格式就可以写成:
content://com.example.app.provider/*Code language: JavaScript (javascript)
而一个能够匹配table1表中任意一行数据的内容URI格式就可以写成:
content://com.example.app.provider/table1/#Code language: JavaScript (javascript)