ContentProvider用途
一个应用只能访问属于自己的SQLite数据库,如果访问其他应用的数据库就会抛出异常,但有时的需要必须操作其他APP的数据库,例如:查看通话记录,短信等。这时就会用到ContentProvider类了,既然能够提供本应用的数据库内容,那一定会有增删改查方法。它是四大组件之一,所以在使用的时候需要在AndroidManifest.xml里
刚刚声明了权限,这里把权限发布出去。
大家是否有这样的疑问?为什么ContentProvider就能解决这样的问题呢?他是怎么解决的呢?这里需要先说Uri和ContentResolver,Uri可以简单理解为一个域名,
它由三部分组成:
完整路径:content://com.example.contentproviderdemo.MyContent/javaScore
(1)content://这部分是Android的Contentprovider规定的,就像http://一样
(2)com.example.contentproviderdemo.MyContent这个部分就是
(3)这个是动态改变的。
ContentResolver就是处理ContentProvider提供出来的数据,ContentProvider需要定义匹配(UriMatcher)模式,找到相符合的才能返回响应的数据,这样处理者得到数据之后就实现了数据的共享。下面是它们的关系图解:
通过上图可以看出:Uri起到一个中间桥梁的作用,ContentResolver先声明想要匹配的Uri,然后系统就会寻找是否有匹配的,有就让ContentProvider进行相应的增删改查操作,返回给ContentResolver,感觉像直接调用了其他APP的数据库一样,其实ContentResolver中的增删改查方法实际就是调用的ContentProvider中的方法,所以参数就是ContentResolver给提供的。
了解一下ContentProvider常用的类:
ContentProvider:内部封装了数据源,外面提供了访问方式,在封装的基础上给匹配规则,正确拿结果。这样就实现了跨应用。
Uri:根据Uri匹配。
ContentResolver:处理ContentProvider提供出来的数据。
代码实现
首先是向外提供数据:
ContentProviderDemo应用的代码:
SQLiteOpenHelper.java
public class DBHelper extends SQLiteOpenHelper {
private static final String BD_NAME = "student.db";
private static int VERSION = 1;
// 表名字
public static final String TABLE_NAME = "javaScore";
public static final String JAVA_ID = "_id";
public static final String JAVA_NAME = "name";
public static final String JAVA_SCORE = "score";
public DBHelper(Context context) {
super(context, BD_NAME, null, VERSION);
System.out.println("数据库-----创建成功");
}
public DBHelper(Context context, String name, int version) {
super(context, name, null, version);
System.out.println("数据库-----创建成功");
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql="create table "+TABLE_NAME+"(_id INTEGER primay key increment,"+JAVA_NAME+" TEXT,"+JAVA_SCORE+" INTEGER)";
db.execSQL(sql);
System.out.println("表-----创建成功");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
MyContent.java
public class MyContent extends ContentProvider {
private SQLiteDatabase db;
private static final UriMatcher matcher = new UriMatcher(
UriMatcher.NO_MATCH);
private static final String AUTHORITY = "com.example.contentproviderdemo.MyContent";
static {
// 参数1:对应XML文件的authorities
// 参数2:通常为表名
// 参数3:匹配成功的返回码
// 完整路径为:content://com.example.contentproviderdemo.MyContent/javaScore
matcher.addURI(AUTHORITY, DBHelper.TABLE_NAME, 1);
// 模糊匹配字符串*
matcher.addURI(AUTHORITY, DBHelper.TABLE_NAME + "/*", 2);
// 模糊匹配数值#
matcher.addURI(AUTHORITY, DBHelper.TABLE_NAME + "/#", 3);
}
// 其他应用首次访问该Contentprovider时会被调用,不要进行耗时操作
@Override
public boolean onCreate() {
db = new DBHelper(getContext()).getReadableDatabase();
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// 匹配一下,看一下是一条数据还是多条数据
int code = matcher.match(uri);
switch (code) {
case 1:// 全部匹配
Cursor cursor = db.query(DBHelper.TABLE_NAME, projection,
selection, selectionArgs, null, null, sortOrder);
return cursor;
case 2:// 模糊匹配字符串
// 获取最后/之后的名字
String name = uri.getLastPathSegment();
Cursor cursor2 = db.query(DBHelper.TABLE_NAME, projection,
"name like '%" + name + "%'", null, null, null, sortOrder);
return cursor2;
case 3:// 根据给定的ID查询
// 取出Uri中的id
long id = ContentUris.parseId(uri);
Cursor cursor3 = db.query(DBHelper.TABLE_NAME, projection,
DBHelper.JAVA_ID + "=?", new String[] { id + "" }, null,
null, sortOrder);
return cursor3;
default:
break;
}
return null;
}
// 返回当前Uri所代表的数据的MIME类型,如果Uri包含多条记录,那么应该vnd.android.cursor.dir/开头
// 一条应该以vnd.android.cursor.item/开头
@Override
public String getType(Uri uri) {
String type = null;
int code = matcher.match(uri);
switch (code) {
case 1:
case 2:// 一条数据
type = "vnd.android.cursor.item/" + AUTHORITY + "."
+ DBHelper.TABLE_NAME + "";
break;
case 3:// 多条数据
type = "vnd.android.cursor.dir/" + AUTHORITY + "."
+ DBHelper.TABLE_NAME + "";
default:
break;
}
return type;
}
// 根据Uri插入values对应的数据
@Override
public Uri insert(Uri uri, ContentValues values) {
int code = matcher.match(uri);
// 返回的插入的id
long id = db.insert(DBHelper.TABLE_NAME, null, values);
// 将插入的ID打包成Uri为了其他应用能够继续访问该条数据
return ContentUris.withAppendedId(uri, id);
}
// 根据Uri删除select条件匹配的全部记录
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int code = matcher.match(uri);
if (code == 3) {
long id = ContentUris.parseId(uri);
return db.delete(DBHelper.TABLE_NAME, DBHelper.JAVA_ID + "=?",
new String[] { id + "" });
}
return 0;
}
// 根据Uri修改select条件匹配的全部记录
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int code = matcher.match(uri);
switch (code) {
case 1:// 没有指定name 和 id
db.update(DBHelper.TABLE_NAME, values, selection, selectionArgs);
break;
case 2:// 取出id
long id = ContentUris.parseId(uri);
// 根据id去更新数
db.update(DBHelper.TABLE_NAME, values, DBHelper.JAVA_ID + " = ?",
new String[] { id + "" });
break;
case 3:// 取出name
String name = uri.getLastPathSegment();
// 根据name去更新
db.update(DBHelper.TABLE_NAME, values, DBHelper.JAVA_NAME
+ " like '%" + name + "%'", null);
break;
default:
break;
}
return 0;
}
}
MainActivity.java
public class MainActivity extends Activity {
private ListView listview;
private SQLiteDatabase db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview = (ListView) findViewById(R.id.listview);
db = new DBHelper(this).getReadableDatabase();
getAllDate();
}
public void btn(View view) {
ContentValues values = new ContentValues();
// 添加一条数据
values.put(DBHelper.JAVA_NAME, "zhangsan");
values.put(DBHelper.JAVA_SCORE, 50);
db.insert(DBHelper.TABLE_NAME, null, values);
// 添加一条数据
values.put(DBHelper.JAVA_NAME, "lisi");
values.put(DBHelper.JAVA_SCORE, 60);
db.insert(DBHelper.TABLE_NAME, null, values);
// 添加一条数据
values.put(DBHelper.JAVA_NAME, "wangwu");
values.put(DBHelper.JAVA_SCORE, 70);
db.insert(DBHelper.TABLE_NAME, null, values);
getAllDate();
}
private void getAllDate() {
Cursor cursor = db.rawQuery("select * from "+DBHelper.TABLE_NAME+"", null);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_2, cursor, new String[]{DBHelper.JAVA_NAME,DBHelper.JAVA_SCORE}, new int[]{android.R.id.text1,android.R.id.text2},SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
listview.setAdapter(adapter);
}
}
AndroidText应用的代码:
因为上述声明了权限,这个需要获取权限才能访问。
public class MainActivity extends Activity {
private ContentResolver resolver;
private ListView lv;
private EditText eName, eId,eScore;
private Uri contentUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
eName = (EditText) findViewById(R.id.eName);
eId = (EditText) findViewById(R.id.eId);
eScore=(EditText) findViewById(R.id.eScore);
resolver = getContentResolver();
lv = (ListView) findViewById(R.id.lv);
contentUri = Uri
.parse("content://com.example.contentproviderdemo.MyContent/javaScore");
}
// 按钮 点击进行查找
public void btnClick(View view){
String name=eName.getText().toString();
String id=eId.getText().toString();
Cursor cursor=null;
if(TextUtils.isEmpty(name)&&TextUtils.isEmpty(id)){//没有name,也没有id
// 参数2:要查找的列
// 参数3:查找条件
// 参数4:条件中的占位符的值
// 参数5:排序
cursor = resolver
.query(contentUri,
null, null, null, null);
}else if(!TextUtils.isEmpty(name)){//有name输入,根据name去查找
//在uri中放进去name值
Uri withAppendedPathUri = Uri.withAppendedPath(contentUri, name);
cursor = resolver.query(withAppendedPathUri, null, null, null, null);
}else if(!TextUtils.isEmpty(id)){//有id输入,根据id查找
//在uri中添加id部分值
Uri uriWithId = ContentUris.withAppendedId(contentUri, Long.parseLong(id));
cursor = resolver.query(uriWithId, null, null, null, null);
}
showAllData(cursor);
}
//展示Cursor中的数据
private void showAllData(Cursor cursor) {
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
MainActivity.this, android.R.layout.simple_list_item_2, cursor,
new String[] { "name", "score" }, new int[] {
android.R.id.text1, android.R.id.text2 });
lv.setAdapter(adapter);
}
//插入数据
public void btnInsert(View view){
String name=eName.getText().toString();
String score=eScore.getText().toString();
//判断呢是否都有数据输入
if(TextUtils.isEmpty(name)&&TextUtils.isEmpty(score)){
Toast.makeText(MainActivity.this, "锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷", 0).show();
}else{
ContentValues values = new ContentValues();
values.put("name", name);
values.put("score", score);
resolver.insert(contentUri, values);
//让lv展示最新全部数据
Cursor cursor = resolver
.query(contentUri,
null, null, null, null);
showAllData(cursor);
}
}
//根据按钮点击---获取id----更新成绩
public void btnUpdate(View view){
String id=eId.getText().toString();
String score=eScore.getText().toString();
//判断是否为空-----如果两个值都为空----不进行更新
if(TextUtils.isEmpty(id)||TextUtils.isEmpty(score)){//都为空
Toast.makeText(MainActivity.this, "id和name为空", 0).show();
}else{
ContentValues values=new ContentValues();
//放进去要更新的成绩值
values.put("score", score);
//把id放进uri中
Uri withAppendedIdUri = ContentUris.withAppendedId(contentUri, Long.parseLong(id));
resolver.update(withAppendedIdUri, values, null, null);
//展示最新数据
Cursor cursor = resolver
.query(contentUri,
null, null, null, null);
showAllData(cursor);
}
}
//按钮删除id
public void btnDelete(View view){
//获得输入的id
String id = eId.getText().toString();
if(TextUtils.isEmpty(id)){//kong
Toast.makeText(MainActivity.this, "锟斤拷锟斤拷锟斤拷id", 0).show();
}else{
//把id放进uri
Uri withAppendedIdUri = ContentUris.withAppendedId(contentUri, Long.parseLong(id));
resolver.delete(withAppendedIdUri, null , null);
Cursor cursor = resolver
.query(contentUri,
null, null, null, null);
showAllData(cursor);
}
}
}