内容提供者
一、使用ContentProvider(内容提供者)共享数据 ContentProvider 在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider
对你应用中的数据进行添删改查。关于数据共享,以前我们学习过文件操作模式,知道通过指定文件的操作模式为Context.MODE_WORLD_READABLE 或Context.MODE_WORLD_WRITEABLE同样也可以对外共享数据。那么,这里为何要使用ContentProvider
对外共享数据呢?是这样的,如果采用文件操作模式对外共享数据,数据的访问方式会因数据存储的方式而不同,导致数据的访问方式无法统一,如:采用xml文件对外共享数据,需要进行xml解析才能读取数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读取数据。
使用ContentProvider对外共享数据的好处是统一了数据的访问方式。
当应用需要通过ContentProvider对外共享数据时,第一步需要继承ContentProvider并重写下面方法:
public class PersonContentProvider extends ContentProvider{
public
boolean onCreate()
public Uri
insert(Uri uri, ContentValues values)
public int
delete(Uri uri, String selection, String[] selectionArgs)
public int
update(Uri uri, ContentValues values, String selection, String[]
selectionArgs)
public
Cursor query(Uri uri, String[] projection, String selection, String[]
selectionArgs, String sortOrder)
public
String getType(Uri uri)}
第二步需要在AndroidManifest.xml使用<provider>对该ContentProvider进行配置,为了能让其他应用找到该ContentProvider ,
ContentProvider 采用了authorities(主机名/域名)对它进行唯一标识,你可以把
ContentProvider看作是一个网站(想想,网站也是提供数据者),authorities 就是他的域名:
<manifest .... >
<application android:icon="@drawable/icon"
android:label="@string/app_name">
<provider android:name=".PersonContentProvider"
android:authorities="cn.itcast.providers.personprovider"/>
</application>
</manifest>
|
二、URI Uri代表了要操作的数据,Uri主要包含了两部分信息:
1》需要操作的ContentProvider ,
2》对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:
ContentProvider(内容提供者)的scheme已经由Android所规定,
a) scheme为:content://
b)
主机名(或叫Authority)用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
c)
路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
要操作person表中id为10的记录,可以构建这样的路径:/person/10
要操作person表中id为10的记录的name字段,
person/10/name
要操作person表中的所有记录,可以构建这样的路径:/person
要操作xxx表中的记录,可以构建这样的路径:/xxx
当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:
要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri =
Uri.parse("content://cn.itcast.provider.personprovider/person")
|
三、UriMatcher类使用介绍 因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris 。掌握它们的使用,会便于我们的开发工作。
UriMatcher类用于匹配Uri,它的用法如下:
首先第一步把你需要匹配Uri路径全部给注册上,如下:
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
UriMatcher
sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://cn.itcast.provider.personprovider/person路径,返回匹配码为1
sMatcher.addURI(“cn.itcast.provider.personprovider”, “person”,
1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配content://cn.itcast.provider.personprovider/person/230路径,返回匹配码为2
sMatcher.addURI(“cn.itcast.provider.personprovider”,
“person/#”, 2);//#号为通配符
switch (sMatcher.match(Uri.parse("content://cn.itcast.provider.personprovider/person/10"))) {
case 1
break;
case 2
break;
default://不匹配
break;
}
注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://cn.itcast.provider.personprovider/person路径,返回的匹配码为1
|
四、ContentUris类使用介绍 ContentUris类用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
1、withAppendedId(uri, id)用于为路径加上ID部分:
Uri uri =
Uri.parse("content://cn.itcast.provider.personprovider/person")
Uri resultUri = ContentUris.withAppendedId(uri, 10);
//生成后的Uri为:content://cn.itcast.provider.personprovider/person/10
2、parseId(uri)方法用于从路径中获取ID部分:
Uri uri =
Uri.parse("content://cn.itcast.provider.personprovider/person/10")
long personid = ContentUris.parseId(uri);//获取的结果为:10
|
Android四大组件之一——内容提供者(主动将私有数据暴露出来)(实际开发中,一般不会写这个,以为这个是将私有数据暴露出来的) <provider
android:name="com.itheima.db.PersonDBProvider"
//一般为当前ContentProvider的类名
android:authorities="com.itheima.db.personprovider" > //(主机名)一般为当前应用包名.用途名
</provider>
1、用户需要手动将private数据给暴露出来 2、内容提供者query中,cursor对应的数据库不能close()掉 3、Android中所有的URI都是以content://开头 I/ActivityThread(1830): Pub cn.zengfansheng.db.personprovider: cn.zengfansheng.db.PersonDBProvider
|
步骤: 1、创建一个类继承ContentProvider 2、在manifest.xml文件中进行配置 provider
android:name="cn.zengfansheng.db.PersonDBProvider"
android:authorities="cn.zengfansheng.db.personprovider"
></provider>
3、定义UriMatcher(addUri,参数二path,指向某一张表/操作)
content://主机/path(表名)/操作
UriMatcher放在上面,有提示代码 private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); private static final int INSERT = 1;// 增
private static final int DELETE = 2;// 删
private static final int UPDATE = 3;// 改
private static final int SELECT = 4;// 查
static {
matcher.addURI("cn.zengfansheng.db.personprovider", "person/insert", INSERT);
matcher.addURI("cn.zengfansheng.db.personprovider", "person/delete", DELETE);
matcher.addURI("cn.zengfansheng.db.personprovider", "person/update", UPDATE);
matcher.addURI("cn.zengfansheng.db.personprovider", "person/select", SELECT);
} 4、在本应用中为增删改查的操作进行uri匹配,如果匹配成功就放行,没有匹配成功就阻止 public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
int match = matcher.match(uri);
if (match == PersonDBProvider.SELECT) {
SQLiteDatabase database = helper.getWritableDatabase();
Cursor cursor = database.query("person", projection, selection, selectionArgs, null, null, sortOrder);
return cursor; // 内容提供者的cursor不能close(),否则为空。
}else {
return null;
}
}
5、另外一个程序,定义内容提供者 ContentResolver resolver = this.getContentResolver(); 6、另外一个程序,通过uri和内容提供者定义的匹配uri进行匹配,匹配成功,就可以继续操作 /**
* 查询select
*
* @param view
*/
public void select(View view) {
//得到内容解析者
ContentResolver resolver = this.getContentResolver();
Uri uri = Uri.parse("content://cn.zengfansheng.db.personprovider/person/select");
Cursor cursor = resolver.query(uri , new String[]{"id","name","phone"}, null, null, null);
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
String phone = cursor.getString(cursor.getColumnIndex("phone"));
Log.i(TAG, "id:" + id + "name:" + name + "phone:" + phone);
}
cursor.close();
} |
核心代码: package cn.zengfansheng.db;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class PersonDBProvider extends ContentProvider {
private PersonSQLiteOpenHelper helper;
private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final int INSERT = 1;// 增
private static final int DELETE = 2;// 删
private static final int UPDATE = 3;// 改
private static final int SELECT = 4;// 查
private static final int SELECTONE = 5;// 查询一条数据
static {
matcher.addURI("cn.zengfansheng.db.personprovider", "person/insert", INSERT);
matcher.addURI("cn.zengfansheng.db.personprovider", "person/delete", DELETE);
matcher.addURI("cn.zengfansheng.db.personprovider", "person/update", UPDATE);
matcher.addURI("cn.zengfansheng.db.personprovider", "person/select", SELECT);
matcher.addURI("cn.zengfansheng.db.personprovider", "person/query/#",
SELECTONE);
}
// 当内容提供者被创建的时候调用,适合做数据的初始化
@Override
public boolean onCreate() {
helper = new PersonSQLiteOpenHelper(getContext());
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
int match = matcher.match(uri);
if (match == PersonDBProvider.SELECT) {
SQLiteDatabase database = helper.getWritableDatabase();
Cursor cursor = database.query("person", projection, selection, selectionArgs, null, null, sortOrder);
return cursor; // 内容提供者的cursor不能close(),否则为空。
} else if (match == PersonDBProvider.SELECTONE) { // 查询一个,根据id
long id = ContentUris.parseId(uri);// content://authority/path/id
SQLiteDatabase database = helper.getWritableDatabase();
Cursor cursor = database.query("person", projection, "id=?",new String[]{id+""}, null, null, sortOrder);
return cursor; // 内容提供者的cursor不能close(),否则为空。
}
return null;
}
@Override
public String getType(Uri uri) {
//The returned MIME type should start with vnd.android.cursor.item for a single record, or vnd.android.cursor.dir/ for multiple items
if (matcher.match(uri) == SELECT) {
return "nd.android.cursor.dir/person"; // 多条数据
} else if (matcher.match(uri) == SELECTONE) {
return "vnd.android.cursor.item/person"; // 一条数据
}
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
int match = matcher.match(uri);
if (match == PersonDBProvider.INSERT) {
SQLiteDatabase database = helper.getWritableDatabase();
database.insert("person", null, values);
database.close();
} else {
throw new IllegalArgumentException("请求的uri不匹配");
}
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int match = matcher.match(uri);
if (match == PersonDBProvider.DELETE) {
SQLiteDatabase database = helper.getWritableDatabase();
database.delete("person", selection, selectionArgs);
database.close();
} else {
throw new IllegalArgumentException("请求的uri不匹配");
}
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int match = matcher.match(uri);
if (match == PersonDBProvider.UPDATE) {
SQLiteDatabase database = helper.getWritableDatabase();
database.update("person", values, selection, selectionArgs);
database.close();
} else {
throw new IllegalArgumentException("请求的uri不匹配");
}
return 0;
}
} |
另外一个应用 import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 1、查询select
*
* @param view
*/
public void select(View view) {
//得到内容解析者
ContentResolver resolver = this.getContentResolver();
Uri uri = Uri.parse("content://cn.zengfansheng.db.personprovider/person/select");//多条数据
Uri uri = Uri.parse("content://cn.zengfansheng.db.personprovider/person/query/10");
Cursor cursor = resolver.query(uri , new String[]{"id","name","phone"}, null, null, null);
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
String phone = cursor.getString(cursor.getColumnIndex("phone"));
Log.i(TAG, "id:" + id + "name:" + name + "phone:" + phone);
}
cursor.close();
}
/**
* 2、插入数据insert
*
* @param view
*/
public void insert(View view) {
ContentResolver resolver = this.getContentResolver();
ContentValues values = new ContentValues();
values.put("name", "小胜");
values.put("phone", "110");
Uri url = Uri.parse("content://cn.zengfansheng.db.personprovider/person/insert");
resolver.insert(url, values);
Log.i(TAG, "插入数据成功");
}
/**
* 3、更新数据update
*
* @param view
*/
public void update(View view) {
ContentResolver resolver = this.getContentResolver();
Uri uri = Uri.parse("content://cn.zengfansheng.db.personprovider/person/update");
ContentValues values = new ContentValues();
values.put("phone", "1111111111");
int update = resolver.update(uri, values, "name=?",
new String[] { "小胜" });
if (update > 0) {
Log.i(TAG, "更新数据成功");
}
}
/**
* 4、删除数据delete
*
* @param view
*/
public void delete(View view) {
ContentResolver resolver = this.getContentResolver();
Uri uri = Uri.parse("content://cn.zengfansheng.db.personprovider/person/delete");
int delete = resolver.delete(uri, "name=?", new String[] { "小胜" });
if (delete > 0) {
Log.i(TAG, "删除数据成功");
}
} |