1.什么是ContentProvider

首先,ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用的比较少。 ContentProvider为不同的软件之间数据共享,提供统一的接口。也就是说,如果我们想让其他的应用使用我们自己程序内的数据,就可以使用ContentProvider定义一个对外开放的接口,从而使得其他的应用可以使用咱们应用的文件、数据库内存储的信息。当然,自己开发的应用需要给其他应用共享信息的需求可能比较少见,但是在Android系统中,很多系统自带应用,比如联系人信息,图片库,音频库等应用,为了对其他应用暴露数据,所以就使用了ContentProvider机制。所以,我们还是要学习ContentProvider的基本使用,在遇到获取联系人信息,图片库,音频库等需求的时候,才能更好的实现功能

2.如何定义一个ContentProvider

Android系统为了让我们更好的对外暴露数据,提供了统一的接口,所以定义了抽象类ContentProvider,因此,如果我们想对外提供数据,我们需要继承ContentProvider,并且实现下面的这几个方法:
onCreate() 当我们的provider初始化时被调用,我们应该在这个方法里面完成部分初始化操作 query() 查询方法,用于给调用者返回数据 insert() 插入操作,用于让外部应用插入数据到内容提供者中 update() 更新操作,用于更新内容提供者的数据 delete() 用于删除数据 getType 返回内容提供者的MIME Type
上面这些方法,当我们继承自ContentProvider的时候,eclipse会自动的给我们添加,但是这并不代表我们每个方法都需要自定义实现。如果我们只希望给其他应用提供数据,而不允许其他应用修改我们的数据,那么我们只需要实现onCreate(),getType()和query()这三个方法就可以了,其他的三个方法我们可以根据业务需求,实现或者是不实现。
因为一般使用ContentProvider向外部暴露数据库的信息,因此,本篇将以使用ContentProvider向其他应用暴露数据库信息为例,讲解ContentProvider的基本使用。
Android中SQLite数据库的创建和使用,本篇不再介绍,不清楚的请看这篇文章 SQLite数据库的简单实用

假设读者已经学会了SQLite数据库的使用,并且已经建立好了数据库,下面我们开始写我们的ContentProvider。 因为注释解析的比较详细,所以就不过多解释了

 /**
* 内容提供者
*
* @author ZhaoKaiQiang
* @time 2014年6月6日
*/
public class StudentProvider extends ContentProvider {
// 数据库操作类,用于获取SQLiteDatabase
private MyDbOpenHelper dbHelper; private static final int STUDENT = 1;
private static final int STUDENTS = 2; // UriMatcher类是一个很重要的类,因为我们需要根据传入的uri,来判断执行相对应的操作
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH); // 静态代码块用于初始化MATCHER需要匹配的uri
static {
// MATCHER.addURI(主机名(用于唯一标示一个ContentProvider,这个需要和清单文件中的authorities属性相同),路径(可以用来表示我们要操作的数据,路径的构建应根据业务而定),返回值(用于匹配uri的时候,作为匹配的返回值));
MATCHER.addURI("com.example.mydbdemo.StudentProvider", "student", STUDENTS);
MATCHER.addURI("com.example.mydbdemo.StudentProvider", "student/#", STUDENT);
} // 进行数据的初始化操作
@Override
public boolean onCreate() {
dbHelper = new MyDbOpenHelper(getContext());
return false;
} // 查询
// 如果uri为 content://com.example.mydbdemo.StudentProvider/student
// 则代表查询所有的student表内的数据
// 如果uri为 content://com.example.mydbdemo.StudentProvider/student/6
// 则代表查询student表内id=6的数据
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = dbHelper.getReadableDatabase();
//判断传入的uri到底匹配哪一个,从而实现不同的业务需求
switch (MATCHER.match(uri)) {
//查询全部的学生信息
case STUDENTS:
//db.query(表明, 要查询的列(是一个String数组), where条件, where条件中的参数, groupBy, having, sortOrder);
return db.query("student", projection, selection, selectionArgs, null, null, sortOrder);
//查询某一个id对应的学生的信息
case STUDENT:
//取出我们要查询的数据的id
long id = ContentUris.parseId(uri);
String where = "id=" + id;
//将selection查询信息拼接到我们的where条件中
if (selection != null && !"".equals(selection)) {
where = selection + " and " + where;
}
return db.query("student", projection, where, selectionArgs, null, null, sortOrder);
//如uri不匹配,抛出不合法参数的异常
default:
throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
} } // 插入
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
switch (MATCHER.match(uri)) {
case STUDENTS:
long id = db.insert("student", "name", values);
return ContentUris.withAppendedId(uri, id);
default:
throw new IllegalArgumentException("Uri不匹配");
} } //删除数据
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int count = 0;
switch (MATCHER.match(uri)) {
case STUDENTS:
count = db.delete("student", selection, selectionArgs);
return count; case STUDENT:
long id = ContentUris.parseId(uri);
String where = "id=" + id;
if (selection != null && !"".equals(selection)) {
where = selection + " and " + where;
}
count = db.delete("student", where, selectionArgs);
return count; default:
throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
}
} //更新数据
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int count = 0;
switch (MATCHER.match(uri)) {
case STUDENTS:
count = db.update("student", values, selection, selectionArgs);
return count; case STUDENT:
long id = ContentUris.parseId(uri);
String where = "id=" + id;
if (selection != null && !"".equals(selection)) {
where = selection + " and " + where;
}
count = db.update("student", values, where, selectionArgs);
return count; default:
throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
}
} // 用于获取MIME Type
@Override
public String getType(Uri uri) {
switch (MATCHER.match(uri)) {
case STUDENT:
return "vnd.android.cursor.item/student";
case STUDENTS:
return "vnd.android.cursor.dir/student";
default:
throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
} } }

我们在定义好我们的ContentProvider之后,因为ContentProvider数据四大组件之一,因此我们还需要在AndroidManifest清单文件中进行注册才能使用,下面是注册信息

 <!-- 不要忘记exported这个属性,如果不加,可能会导致外部程序访问失败,错误信息为权限拒绝 -->
<!-- authorities这个属性就是我们在ContentProvider中使用的addURI方法时的第一个参数的取值 -->
<provider
android:name="com.example.mydbdemo.StudentProvider"
android:exported="true"
android:authorities="com.example.mydbdemo.StudentProvider" >
</provider>

注意,provider的声明和activity一样,都是在application节点进行声明的。
至此,我们就完成了我们自己的ContentProvider的生命,其他的应用现在就可以使用我们往外部暴露的数据信息了。

3.外部应用如何使用我们的ContentProvider

我们已经定义好了我们自己的ContentProvider,那么外部应用如何调用呢? 下面,我将新建一个测试单元工程,完成对ContentProvider的各个方法的测试
添加方法测试

 //使用ContentProvider添加数据的测试
public void testadd() throws Throwable {
//获取ContentResolver对象,完成对ContentProvider的调用
ContentResolver contentResolver = this.getContext().getContentResolver();
//构建我们的uir,这个uri
Uri insertUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student");
ContentValues values = new ContentValues();
values.put("name", "zhaokaikai");
values.put("age", 91);
values.put("school", "bbbb");
//返回值为我们刚插入进入的数据的uri地址
Uri uri = contentResolver.insert(insertUri, values);
Log.i(TAG, uri.toString());
}

删除方法测试

 //使用ContentProvider删除数据的测试
public void testDelete() throws Throwable {
ContentResolver contentResolver = this.getContext().getContentResolver();
//删除id为6的学生信息
Uri deleteUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student/6");
contentResolver.delete(deleteUri, null, null);
}

修改方法测试

 //使用ContentProvider更新数据的测试
public void testUpdate() throws Throwable {
ContentResolver contentResolver = this.getContext().getContentResolver();
//更新id = 6 的学生信息
Uri updateUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student/6");
ContentValues values = new ContentValues();
values.put("name", "testUp");
values.put("age", "101");
values.put("school", "ccccc");
contentResolver.update(updateUri, values, null, null);
}

查询

 //使用ContentProvider查询数据的测试
public void testFind() throws Throwable {
ContentResolver contentResolver = this.getContext().getContentResolver();
//这个uri用于查询所有的数据,若查询某个id的数据,则构建下面的uri
//Uri selectUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student/要查询的id");
Uri selectUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student");
Cursor cursor = contentResolver.query(selectUri, null, null, null, "id desc");
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
String school = cursor.getString(cursor.getColumnIndex("school"));
Log.i(TAG, "id=" + id + ",name=" + name + ",age=" + age +",school="+school);
}
}

上面的方法都经过了单元测试。
好了,至此,我们就使用ContentProvider实现了在第三方应用中对我们应用的数据库进行增删改查等操作,如有疑问,请留言。

转载自:http://www.it165.net/pro/html/201406/15166.html

Android中内容提供者ContentProvider的详解的更多相关文章

  1. Android 中内容提供者的使用

    在Android中内容提供者主要是用于不同程序之间的数据共享.内容提供器的用法一般有两种,一种是使用现有的内容提供器来读取和操作相应程序的数据,另一种是创建自己的内容提供器,供其他的程序访问. 使用现 ...

  2. Android基础内容提供者ContentProvider的使用详解(转)

    1.什么是ContentProvider 首先,ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用的比较少. ContentProvider为不 ...

  3. [Android Pro] 内容提供者ContentProvider的基本使用

    一.ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.ContentProvider为存储和获取数据提 ...

  4. Android中全局搜索(QuickSearchBox)详解

    http://blog.csdn.net/mayingcai1987/article/details/6268732 1. 标题: 应用程序如何全面支持搜索 2. 引言: 如果想让某个应用程序支持全局 ...

  5. Android中measure过程、WRAP_CONTENT详解以及 xml布局文件解析流程浅析

    转自:http://www.uml.org.cn/mobiledev/201211221.asp 今天,我着重讲解下如下三个内容: measure过程 WRAP_CONTENT.MATCH_PAREN ...

  6. Android之内容提供者ContentProvider的总结

    本文包含以下知识点: ContentProvider Uri 的介绍 ContentResolver: 监听ContentProvider的数据改变 一:ContentProvider部分 Conte ...

  7. Android中_TextView属性的XML详解 包括单行显示等等。

    <pre name="code" class="html">属性名称 描述 android:autoLink 设置是否当文本为URL链接/email ...

  8. Android 中使用MediaRecorder进行录像详解(视频录制)

    在这里给出自己的一个测试DEMO,里面注释很详细.简单的视频录制功能. package com.video; import java.io.IOException; import android.ap ...

  9. Android中的Service的使用详解

    按运行地点分类: 类别 区别 优点 缺点 应用 本地服务(Local) 该服务依附在主进程上, 服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不 ...

随机推荐

  1. (转)Android四大组件——Activity跳转动画、淡出淡入、滑出滑入、自定义退出进入

    文章转自:http://blog.csdn.net/qq_30379689/article/details/52494270 Activity跳转动画.淡入淡出.滑入滑出.自定义退出进入 前言: 系统 ...

  2. 基于ASP.NET的高校辅导员工作管理系统的设计与实现--论文随笔(四)

    一.基本信息 标题:基于ASP.NET的高校辅导员工作管理系统的设计与实现 时间:2017 出版源:南通理工学院 关键词:ASP.NET; SQL Server; 高校; 管理系统; 辅导员; 二.研 ...

  3. 1,postman的安装

    1,下载postman 2,安装,下载和自己系统相对应的版本 本人下载的是window版本的,直接一步步安装就行 打开后进入下边的界面 建议使用native版本的postman,chrome插件的po ...

  4. linux就该这么学,第五课,

    今天讲的比较难理解,要重预习和复习 今天讲了2个多小进,主要讲了SHELL,shell的组成:第一行为脚本声明 #!/bin/bash   ,第二行为脚本的注释信息,第三为 脚本的执行语句 接收用户参 ...

  5. redis在游戏服务器中的使用初探(一) 环境搭建

    这里我们尝试在游戏服务器中的数据处理中使用redis 通过该系列文章能够学习 redis的基本操作 源码编译 客户端开源库的编译和使用 以及在游戏服务器中的缓存使用 作为初次摸索 尽量使得环境简单  ...

  6. [uboot] (番外篇)uboot relocation介绍

    http://blog.csdn.net/ooonebook/article/details/53047992 以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为 ...

  7. ubuntu无法打开software-center

    ubuntu无法打开software-center BUG: 在ubuntu14.04LTS版本下,点击软件中心图标,过了一会软件未能启动,没有动静.用命令行启动报如下错误: perrin@Littl ...

  8. Vuejs——(10)组件——父子组件通信

    版权声明:出处http://blog.csdn.net/qq20004604   目录(?)[+]   本篇资料来于官方文档: http://cn.vuejs.org/guide/components ...

  9. unigui结合JS方法记录

    在js中界面上所有组件都当成html里来控制 .控制按钮事件  document.getElementById(MainForm.UniButton4.getId()).click(); 这个方法让J ...

  10. 有关C++模板inline的高性能在lambda与function的体现

    前两天在群里跟人讨论到写库时对于lambda和function的取舍,跑了写测试查了些资料后基本得出结论: 如果没有自由变量的情况下,一般不要用function. 如果有自由变量的话,C++中的lam ...