对于上一篇博客android_内容提供者和内容解析者_简单入门
里面所出现的问题,现在来描述一下:
1. 应用程序在发布上去的时候,会对外公布口令(以Log形式), 所以只要有人拿过来这个口令,不管是谁,都帮他干活。
2. 在代码中, 假设这个应用有100张表想暴露出去,并且刚好有100个APP来访问不同的表,那么这个时候如何分辨出,哪一个应用访问哪一个表呢? 就要根据URIMatcher来界定了。
问题出现了,怎么解决?
答案:就是使用URIMatcher来解决一下
URIMatcher是一个种匹配的规则的升级版
现在我们重新定义一下,
内容提供者应该怎么去定义:
步骤:
1. 定义一个类,继承ContentProvider
2. 注册内容提供者,要注意:要添加作者名
3. 在内容提供者里面声明URIMatcher
4. 使用静态代码块预设匹配规则
5. 在CRUD方法里面先判断uri ,如果正确,就操作数据库
步骤写好:
现在代码演示一下:
1. 定义一个类,继承ContentProvider
public class BankBackDoor extends ContentProvider {
private static final String TAG = "BankBackDoor";
//第三步:在内容提供者里面声明URIMatcher
//声明了一个URI的匹配器 参数的意思是: 如果没有匹配,那么久返回这个code
//UriMatcher.NO_MATCH就是我们常量-1
static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
static{
//http://www.baidu.com/news.html;
//content://com.itheima.bank.BACKDOOR/path
/*
* 参数一: 作者名
* 参数二: path路径(一般就是写表名)
* 参数三: 一旦匹配上了这条uri,那么久返回100匹配码
*
*/
//第四步: 使用静态代码块预设匹配规则
matcher.addURI("com.itheima.bank.BACKDOOR", "account", 100);
matcher.addURI("com.itheima.bank.BACKDOOR", "stu", 101);
matcher.addURI("com.itheima.bank.BACKDOOR", "teacer", 102);
}
@Override
public Uri insert(Uri uri, ContentValues values) {
//第五步:在CRUD方法里面先判断uri ,如果正确,就操作数据库
if(matcher.match(uri) == 100){
Log.d(TAG, "insert---");
//往account表里面添加数据
//1 。 得到数据库帮助类对象
//2. 添加数据
BankOpenHelper helper = new BankOpenHelper(getContext());
SQLiteDatabase db = helper.getWritableDatabase();
db.insert("account",null, values);
db.close();
}else{
throw new IllegalArgumentException("口令错误,滚犊子..");
}
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
if(matcher.match(uri) == 100){
Log.d(TAG, "delete---");
BankOpenHelper helper = new BankOpenHelper(getContext());
SQLiteDatabase db = helper.getWritableDatabase();
db.delete("account", selection, selectionArgs);
db.close();
//参数一: 具体是什么位置的数据发生了改变
//参数二:具体的内容观察者对象, 如果是null , 那么表明不告诉具体的某一个人,
getContext().getContentResolver().notifyChange(uri, null);
}else{
throw new IllegalArgumentException("口令错误,滚犊子..");
}
return 0;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
if(matcher.match(uri) == 100){
Log.d(TAG, "query---");
BankOpenHelper helper = new BankOpenHelper(getContext());
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.query("account", projection, selection, selectionArgs, null, null, sortOrder);
return cursor ;
}else{
throw new IllegalArgumentException("口令错误,滚犊子..");
}
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
if(matcher.match(uri) == 100){
Log.d(TAG, "update---");
BankOpenHelper helper = new BankOpenHelper(getContext());
SQLiteDatabase db = helper.getWritableDatabase();
db.update("account", values, selection, selectionArgs);
db.close();
//参数一: 具体是什么位置的数据发生了改变
//参数二:具体的内容观察者对象, 如果是null , 那么表明不告诉具体的某一个人,
getContext().getContentResolver().notifyChange(uri, null);
}else{
throw new IllegalArgumentException("口令错误,滚犊子..");
}
return 0;
}
//-----------------------------
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
return false;
}
}
第二步: 注册内容提供者,要注意:要添加作者名(口令)
<!-- authorities : 就是其他程序来访问数据的时候与我们自己的contentProvider对接的口令 -->
<provider android:name="com.itheima.bank.BankBackDoor"
android:authorities="com.itheima.bank.BACKDOOR" android:exported="true"></provider>
上面的5步就可以设置好一个内容提供者了.
既然内容提供者已经升级了,那我们的内容访问者应该怎么匹配呢?
现在代码演示一下
public void insert(View v){
//ContentProvider 内容提供者 暴露数据
//ContentResolver 内容解析者
//1. 得到内容解析者对象
ContentResolver resolver = getContentResolver();
//到底要插入哪一个数据库的表 -- 操作内容提供者的口令
//content:// 这个前缀必须要加上,否则对接失败
Uri uri = Uri.parse("content://com.itheima.bank.BACKDOOR/account");
//准备数据
ContentValues values = new ContentValues();
values.put("name", "aobama");
values.put("money", 1000);
//2. 执行insert方法
resolver.insert(uri, values);
}
其实需要访问升级之后的内容提供者的关键还是
Uri uri = Uri.parse(“content://com.itheima.bank.BACKDOOR/account”);
在我们最后后面,加上了,内容提供者的path(一般就是表名).
Uri匹配上了,就可以成功的访问了
提醒:
学习内容提供者的目的
- 在实战开发当中很少给自己的应用程序定义一个内容提供者。
- 理解内容提供者的工作原理,以及背后都是如何操作。
- 更多的情况是,我们需要访问内容提供者,当然这些内容提供者不是其他应用定义的,而是系统应用中定义的。
- 用的比较多的: 联系人的内容提供者 、 短信的内容提供者 、多媒体的内容提供者(image\audio\video)