android菜鸟学习笔记21----ContentProvider(一)ContentProvider的简单使用
ContentProvider是Android四大组件之一,它用来封装数据,并通过ContentResolver接口将数据提供给其他应用。只有当需要在多个应用之间共享数据时才会用到ContentProvider。
多个应用共享数据时,如何区分是哪个应用中的那部分数据呢?
ContentProvider通过Uri标识具体某个应用的某些数据。当一个应用提供了ContentProvider向其他应用共享数据时,该应用在其ContentProvider中添加标识自己特定数据的Uri,然后其他应用想要获得这些数据时,则可以通过向ContentResolver接口的方法传入标识要访问的数据的Uri即可。

如应用B和应用C都向外提供数据,他们就需要在自己提供的ContentProvider中分别指明自己所能解析的Uri。应用A要访问应用B和应用C提供的数据,就需要使用ContentResolver接口,要向该接口的访问数据的方法中传入特定的Uri以区分是要访问应用B的数据,还是要访问应用C的数据。
应用之间共享数据需要用到的类和接口有:ContentProvider、ContentResolver、Uri、UriMatcher、ContentUris等。
下面一一学习这几个类和接口的简单使用:
1)ContentProvider:
该类是一个抽象类,要在自己应用中使用ContentProvider对象,需要自定义类继承ContentProvider类,并实现几个主要的抽象方法:

onCreate()方法: 其它应用第一次访问该ContentProvider时被调。
insert()方法:外部应用使用此方法添加数据。
delete()方法:外部应用使用此方法删除数据。
update ()方法:外部应用使用此方法更新数据。
query()方法:外部应用使用此方法查询数据。
getType()方法: 主要用于匹配数据类型,返回当前Uri所代表数据的MIME类型。如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/自定义类型。数据属于非集合类型数据,应该返回vnd.android.cursor.item/自定义类型。
2)ContentResolver:
是一个接口,可以通过Context.getContentResolver()获取该接口的实例,当在自己应用中要访问别的应用ContentProvider提供的数据时,需要获取该接口的实例,然后调用该接口的insert()、update()、query()、delete()等方法,最终会调用对应ContentProvider中同名的方法,实现共享数据的增删改查操作。
3)Uri:
也是一个抽象类。
Uri标准的格式是:schema://主机名authority/path[/ID]
后面的ID部分根据访问需要,可能没有。
如:content://cn.csc.app1/student标识要访问的是cn.csc.app1所标识的应用中的student表。
ContentProvider中Uri的schema部分一般为content://
authority用来标识要访问的是哪个ContentProvider,通常用能唯一标识应用的包名作为authority。
path部分,则标识我们要访问的是哪些数据,如student表示我们要访问的是student表的数据。
若加上ID部分,如content://cn.csc.app1/student/10,一般被用来表示我们要访问的是student表中的id为10的那条数据。
uri中可以使用通配符:
*:表示匹配任意长度的字符串
#:表示匹配任意长度的数字串
如匹配任意表的uri可以表示为:content://cn.csc.app1/*
匹配student表中任意一条记录的uri:content://cn.csc.app1/student/#
常用到的是Uri中的一个静态方法:

parse()用来将字符串表示的uri解析为Uri对象。
4)UriMatcher:

Uri匹配的一个工具类,一般用在ContentProvider中:
一般使用常量NO_MATCH作为参数,构造UriMatcher对象,然后调用addURI()方法向该对象中添加URI,使用match()方法判断传入的Uri的匹配结果。
addURI()方法的参数说明:
authority:Uri中的authority用于标识是哪个ContentProvider
path:Uri中的path部分,标识要操作的是哪张表
code:用于设置当前添加的Uri的标识码,当使用match方法,传入一个Uri参数时,会将匹配到的Uri对应的code返回,以指明当前匹配到哪个Uri。
5)ContentUris:
一个实用的对Uri进行操作的工具类

parseId():用来获取传入的Uri中的Id部分
withAppendId():用于将传入的Uri和id拼接起来。
下面是实际编写ContentProvider的一个简单示例:
第一步:要先有一个数据库帮助类,以便于进行数据库增删改查操作
package cn.csc.content_provider.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.util.Log;
public class MySqliteHelper extends SQLiteOpenHelper {
public static final String TAG = "MYSQLITEHELPER";
public static final String CREATE_STUDENT = "create table t_student (" +
"id integer primary key, name varchar(20), " +
"gender varchar(10), age integer)";
public static final String CREATE_TEACHER = "create table t_teacher(" +
"id integer primary key, name varchar(20))";
public MySqliteHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}
@Override
public void onOpen(SQLiteDatabase db) {
Log.i(TAG,"open db");
super.onOpen(db);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_STUDENT);
db.execSQL(CREATE_TEACHER);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
第二步:编写自己的ContentProvider类,继承自ContentProvider类,并实现主要的方法:
1)编写MyContentProvider继承自ContentProvider类:
public class MyContentProvider extends ContentProvider {
@Override
public int delete (Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public Uri insert (Uri uri, ContentValues values){
// TODO Auto-generated method stub
return null;
}
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
return false;
}
@Override
public Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
return null;
}
@Override
public int update (Uri uri, ContentValues values, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
}
2)注意,四大组件都需要在Manifest.xml文件中注册:
在Application节点中添加:
<provider android:name="cn.csc.content_provider.MyContentProvider"
android:authorities="cn.csc.content_provider"></provider>
3)为该类添加一个静态UriMatcher字段,用于后续工作中Uri的匹配工作,并通过静态代码块,添加能够匹配的Uri:
private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final int STUDENT_DIR = 0;
private static final int STUDENT_ITEM = 1;
private static final int TEACHER_DIR = 2;
private static final int TEACHER_ITEM = 3;
static{
matcher.addURI("cn.csc.content_provider", "t_student", STUDENT_DIR);
matcher.addURI("cn.csc.content_provider", "t_student/#", STUDENT_ITEM);
matcher.addURI("cn.csc.content_provider", "t_teacher", TEACHER_DIR);
matcher.addURI("cn.csc.content_provider", "t_teacher/#", TEACHER_ITEM);
}
4)实现父类中的几个抽象方法:
@Override
public int delete (Uri uri, String selection, String[] selectionArgs) {
int cnt = -1;
switch(matcher.match(uri)){
case STUDENT_DIR:
cnt = db.delete("t_student", selection, selectionArgs);
break;
case STUDENT_ITEM:
long id = ContentUris.parseId(uri);
cnt = db.delete("t_student", "id = ?", new String[]{id+""});
break;
case TEACHER_DIR:
cnt = db.delete("t_teacher", selection, selectionArgs);
break;
case TEACHER_ITEM:
long id1 = ContentUris.parseId(uri);
cnt = db.delete("t_teacher", "id = ?", new String[]{id1+""});
break;
}
return cnt;
}
@Override
public String getType(Uri uri) {
switch(matcher.match(uri)){
case STUDENT_ITEM:
return "vnd.android.cursor.item/student";
case TEACHER_ITEM:
return "vnd.android.cursor.item/teacher";
case STUDENT_DIR:
return "vnd.android.cursor.dir/student";
case TEACHER_DIR:
return "vnd.android.cursor.dir/teacher";
}
return null;
}
@Override
public Uri insert (Uri uri, ContentValues values){
switch(matcher.match(uri)){
case STUDENT_DIR:
long id = db.insert("t_student", null, values);
return ContentUris.withAppendedId(uri, id);
case TEACHER_DIR:
return ContentUris.withAppendedId(uri, db.insert("t_teacher", null, values));
}
return null;
}
@Override
public boolean onCreate() {
helper = new MySqliteHelper(getContext(), "students.db", null, 1);
db = helper.getWritableDatabase();
return true;
}
@Override
public Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Cursor cursor = null;
switch (matcher.match(uri)) {
case STUDENT_ITEM:
long id = ContentUris.parseId(uri);
cursor = db.query("t_student", projection, "id = ?", new String[]{id+""}, null, null, sortOrder);
break;
case TEACHER_ITEM:
long id1 = ContentUris.parseId(uri);
cursor = db.query("t_teacher", projection, "id = ?", new String[]{id1+""}, null, null, sortOrder);
break;
case STUDENT_DIR:
cursor = db.query("t_student", projection, selection, selectionArgs, null, null, sortOrder);
break;
case TEACHER_DIR:
cursor = db.query("t_teacher", projection, selection, selectionArgs, null, null, sortOrder);
break;
}
return cursor;
}
@Override
public int update (Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int cnt = -1;
switch (matcher.match(uri)) {
case STUDENT_ITEM:
long id = ContentUris.parseId(uri);
cnt = db.update("t_student", values, "id = ?", new String[]{id+""});
break;
case TEACHER_ITEM:
long id1 = ContentUris.parseId(uri);
cnt = db.update("t_teacher", values, "id = ?", new String[]{id1+""});
break;
case STUDENT_DIR:
cnt = db.update("t_student", values, selection, selectionArgs);
break;
case TEACHER_DIR:
cnt = db.update("t_teacher", values, selection, selectionArgs);
break;
}
return cnt;
}
5)新建一个项目,在其中通过ContentResolver访问该ContentProvider提供的数据:
public class MyTest extends AndroidTestCase {
public void testInsert(){
Uri uri = Uri.parse("content://cn.csc.content_provider/t_student");
ContentValues values = new ContentValues();
values.put("name", "dqrcsc");
values.put("gender", "male");
values.put("age", 24);
Uri uri2 = getContext().getContentResolver().insert(uri, values);
Log.i("Test",uri2.toString());
}
public void testUpdate(){
Uri uri = Uri.parse("content://cn.csc.content_provider/t_student/2");
ContentValues values = new ContentValues();
values.put("name", "bbbb");
values.put("gender", "female");
values.put("age", 12);
int i = getContext().getContentResolver().update(uri, values, null, null);
Log.i("Test",i+"");
}
public void testQuery(){
Uri uri = Uri.parse("content://cn.csc.content_provider/t_student/3");
Cursor cursor = getContext().getContentResolver().query(uri, new String[]{"id","name","gender","age"}, null, null, null);
while(cursor != null && cursor.moveToNext()){
Log.i("Test",cursor.getString(0)+","+cursor.getString(1)+","+cursor.getString(2)+","+cursor.getString(3));
}
}
public void testQueryAll(){
Uri uri = Uri.parse("content://cn.csc.content_provider/t_student");
Cursor cursor = getContext().getContentResolver().query(uri, new String[]{"id","name","gender","age"}, null, null, null);
while(cursor != null && cursor.moveToNext()){
Log.i("Test",cursor.getString(0)+","+cursor.getString(1)+","+cursor.getString(2)+","+cursor.getString(3));
}
}
public void testDelete(){
Uri uri = Uri.parse("content://cn.csc.content_provider/t_student/6");
int i = getContext().getContentResolver().delete(uri, null, null);
Log.i("Test",i+"");
}
}
以上,就是ContentProvider的简单使用。
android菜鸟学习笔记21----ContentProvider(一)ContentProvider的简单使用的更多相关文章
- android菜鸟学习笔记13----Android控件(二) 自定义控件简单示例
有时候,可能觉得系统提供的控件太丑,就会需要自定义控件来实现自己想要的效果. 以下主要参考<第一行代码> 1.自定义一个标题栏: 系统自带的标题栏很丑,且没什么大的作用,所以我们之前会在o ...
- android菜鸟学习笔记23----ContentProvider(三)利用内置ContentProvider监听短信及查看联系人
要使用一个ContentProvider,必须要知道的是它所能匹配的Uri及其数据存储的表的结构. 首先想办法找到访问短信及联系人数据的ContentProvider能接受的Uri: 到github上 ...
- android菜鸟学习笔记22----ContentProvider(二)ContentObserver的简单使用
现在有这样一个应用A通过ContentProvider提供自己的数据给其他应用,应用B通过ContentResolver获取应用A中提供的数据,并将其展示在ListView中,而应用C通过Conten ...
- android菜鸟学习笔记8----Activity(一)
Activity是android应用程序中重要的组件之一,常听到的android四大组件是Activity.Service.BroadcastReceiver和ContentProvider.它间接继 ...
- android菜鸟学习笔记30----Android使用百度地图API(一)准备工作及在应用中显示地图
1.准备工作: 百度地图API是免费开放的,但是需要申请API Key: 1)先注册一个百度开发者帐号 2)进入百度开放服务平台http://developer.baidu.com/ 3)进入LBS云 ...
- android菜鸟学习笔记29----Android应用向用户发送提示信息的方式总结
常见的向用户发送提示信息的方式有3种,分别为: 1)发送Toast信息 2)弹出对话框 3)发送通知 总结如下: 方式1:发送Toast信息: 这种方式最简单,在之前的学习中多次使用过.Toast是在 ...
- android菜鸟学习笔记27----Fragment的简单使用
1.Fragment的生命周期: 简单在新建一个MyFragment继承自Fragment,重写各个生命周期回调方法,各个方法中直接输出标识相关函数被调用的信息. 重写MainActivity的各个生 ...
- android菜鸟学习笔记24----与服务器端交互(一)使用HttpURLConnection和HttpClient请求服务端数据
主要是基于HTTP协议与服务端进行交互. 涉及到的类和接口有:URL.HttpURLConnection.HttpClient等 URL: 使用一个String类型的url构造一个URL对象,如: U ...
- android菜鸟学习笔记20----Android数据存储(四))Android数据库操作
Android内置了一个名为SQLite的关系型数据库,这是一款轻量型的数据库,操作十分简便.SQLite与别的数据库不同的是,它没有数据类型.可以保存任何类型的数据到你所想要保存的任何表的任何列中. ...
随机推荐
- vertex buffer 数据结构 如何读vb的memory pool
vertex attribute (declaration) vertex stream (memory pool) 这两部分 通过attribute 里面对memory的描述把两部分 vbo ...
- ElasticSearch 结构化搜索
1.介绍 结构化搜索(Structured search) 是指有关探询那些具有内在结构数据的过程.比如日期.时间和数字都是结构化的:它们有精确的格式,我们可以对这些格式进行逻辑操作. 比较常见的操作 ...
- Linux&Windows下批量修改文件后缀
Linux下从给定文件夹中找出小于1M的文件,并批量添加.gif后缀 先看一下文件夹下的目录的格式 ll -Sh -rw-rw-r-- 1 yangkun yangkun 17M May 10 15: ...
- 转:阿里 Weex 思路与实战(web相关)
Weex——关于移动端动态性的思考.实现和未来 2016-04-05 勾股.伊耆 移动开发前线 本文由手机淘宝技术团队赵锦江(勾股).黄金涌(伊耆)等专家创作.手淘作为电商应用,对客户端/前端的动态性 ...
- mysql 存储过程 演示样例代码
drop procedure if exists P_SEQUENCE; /** 暂省略包 @AUTO LIANGRUI 2014/6/27 T_PRO_PRODUCT 表 排序 对整个表进行按序号排 ...
- 倍福TwinCAT(贝福Beckhoff)基础教程5.1 TwinCAT-4 获取本机名称和网卡名称
使用命令FB_GetHostName来获取本机名称,返回的是一个字符串 使用命令FB_GetAdaptersInfo获取网卡信息(注意采集到的是一个非常复杂的类型,本身是一个数组,数组的每个元素又 ...
- java中native方法的使用
在非常多情况下,java须要调用其它语言的代码,比方c的代码.那么这个时候java中native方法就发挥作用了.以下就介绍native方法的使用. 一.JNI使用流程 a.编写带有native声明的 ...
- HDU1789 Doing Homework again 【贪心】
Doing Homework again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- 转python调用Go代码
Go 1.5发布了,其中包含了一个特性:可以编译生成动态链接库,经试验,生成的.so文件可以被python加载并调用.下面举个例子: 先写一个go文件main.go: package main imp ...
- performSelector 方法的自己主动俘获特性
局部变量自己主动俘获 偶然在调试中发现,performSelector 方法具有自己主动俘获变量的特性.试看例如以下代码: CGFloat c = _addViewShowing ? 0 : 80; ...