http://blog.csdn.net/ahuier/article/details/11882059
1. Content Providers 介绍
Content Providers 管理访问结构化的数据集。它们可以封装这些数据,并且为定义安全的数据提供机制。Content providers 是标准的接口,它能将一个线程中的数据与其他线程中的运行的代码进行连接。也就是说 Content providers 支持跨应用间的访问。
当你想要在 Content provider[内容提供者] 中访问数据,你要在你的应用程序的 Context 中使用 ContentResolver[内容解析者] 对象与 provider 进行连接作为客户端[通过 Cotext中getContentResolver()方法] 。这个ContentResolver 会与provider对象进行连接,provider 它是一个继承Content provider的类的实例。provide这个对象会接受从客户端请求的数据,执行请求动作,返回结果。
如果你不打算将自己的数据分享给其他应用程序,就不必要开发自己的 内容提供者[提供者], 然而你想要在你的应用程序中提供自定义的搜索建议你需要开发内容提供者,如果你想要复制数据或者文件到其它应用程序,你就需要拥有自己的 provider 。
Android自己提供了一个 content providers 来管理数据,如果 音频,视频,或者个人信息等。你可以在 android.provider 包中查看,这些提供者可以给任何应用程序所访问。
1). 你需要提供完整的数据和文件给其他的应用程序.
2). 你想要允许用户从你的应用程序复制完整的数据到其他的应用程序
3). 你想要使用搜索框架来提供自定义的搜索建议。
2) 创建内容提供者需要掌握的知识
1). 自定义一个内容提供者供别的应用程序去访问,Content provider 是基于数据库的,它在外层封装了有一套非常规范的增删查改的操作数据库的对外接口,如下图所示
2). 查看API文档中 ContentProvider 类的说明,可以发现这是一个抽象类
Content providers是Android应用程序中主要的组成部分之一,为应用程序提供对外的内容,它封装了数据然后提供给那些通过简单 ContentResolver接口的应用程序,这些数据是可以跨应用访问的。
对与解析者来说,它会通过 ContentResolver 会发出一个请求,这个请求是否通过是通过去检查由系统给予的 URI 的授权,授权是由 content provider 注册的,在AndroidMainifest.xml 中去注册这种授权。UriMatcher 类可以帮助解析 URI.[也就是通过这个类去匹配URI,详细参考第5点 ]
在这里为什么要注册 URI授权呢?
原因是一个应用程序中可以有多个 content provider, 但是每一个content provider 的授权都是唯一的,所以内容解析者可以通过这种URL的授权来找到自己想要的 content provider. 这里的 URI 的授权也可以理解为content provider对外的一个访问的路径。
3). 注意定义好一个内容提供者之后需要在 AndroidMainifest.xml 中注册
android:authorities 授权属性,表示外部应用程序访问当前内容提供者的标示符,它是自定义的,一般我们是以 "包名 + 类名" 的形式来定义的。有些人可以理解为 URI 路径
4). 查看 UriMatcher 类的概要描述
这是一个在 content provider 中帮助匹配 URIs 的实用类。
查看 public void addURI (String authority, String path, int code)方法
这个方法是用来表示在 content provider 里面添加外部对其的匹配的规则,当 URI 被匹配的时候,就会返回 code 码, URI节点可以精确的匹配字符串, "*" 号匹配任何的字符串 "#" 号只能匹配数字。[比如删除一条记录中 ID 往往是数字]
参数说明
authority : 授权, 就是 AndroidMainifest.xml 中的授权
path : 匹配路径(通常是一个表名)[* 可以作为匹配任意字符的通配符, # 可以作为匹配数字的通配符]。【注意这里如果是单条记录,需要添加 /# 标示符】
5). 查看 content provider 中的 public abstract String getType (Uri uri) 方法
根据给定的 URI 来实现处理 MIME类型的请求, 对于单条记录返回的 MIME 类型是以 vnd.android.cursor.item 开始的, 对于多条记录返回的MIME类型是以vnd.android.cursor.dir/ 开始的. 这个方法可以在多线程环境下被调用。 详细参考Processes and Threads.
6). 查看 content provider 中 public abstract Uri insert (Uri uri, ContentValues values) 方法
实现这个方法来处理插入一个新行的请求, 在插入后可以友好的调用 notifyChange() 方法。
参数说明:
uri : 这种格式 "content:// URI" 的插入请求[后续会认真的讲解这一部分内容]。 此处不为空
values : 添加到数据库的 ContentValues 类型集合。博客前面章节讲过次内容,详情可以去参考。此处不为空
返回
新插入选项的URI,可以给其他用户去使用。
7). 删除操作
查看 content provider 的 public abstract int delete (Uri uri, String selection, String[] selectionArgs) 方法
实现这个方法主要是用来处理删除一行或者多行的请求操作,实现这个删除操作需要 有 selection 语句,你可以在删除之后调用 notifyDelete() 方法来做友好的提示
实现这个方法还需要在 URI的末尾解析出行的ID,如果一个指定的行被删除之后,例如,客户端在创建SQL语句的时候会通过 content://contacts/people/22 的这个URI,来解析出末尾的ID号,确定删除ID为 22 的这个记录。
参数说明:
URI : 完整的URI路径,包括行ID
selection : 可选项,在删除行的时候适用
返回 :
影响数据库的行数
3. 代码实现
1) actvity_main.xml 程序界面的布局文件, 这里只是定义了5个按钮,不贴出来了
2) DBOpenHelper.java 主要是用来做数据库的创建使用
- package com.android.contentproviderdemo;
-
- import android.content.Context;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteOpenHelper;
- import android.util.Log;
-
- public class DBOpenHelper extends SQLiteOpenHelper {
-
- private static final String TAG = "DBOpenHelper";
- private static String name = "mydb.db";
- private static int version = 1;
-
- public DBOpenHelper(Context context) {
- super(context, name, null, version);
-
- }
-
- @Override
- public void onCreate(SQLiteDatabase database) {
-
- String sql = "create table student (id integer primary key autoincrement, name varchar(64), address varchar(64))";
- database.execSQL(sql);
- Log.i(TAG, "ahuier--> SQLite create succeed!");
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-
-
- }
-
- }
3) StudentProvider.java 也就是本例子中最重要的代码,实现 Content Provider中增删查改的操作
- package com.android.contentproviderdemo;
-
- 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;
- import android.util.Log;
-
- public class StudentProvider extends ContentProvider {
-
- private final String TAG = "StudentProvider";
- private DBOpenHelper helper = null;
-
- private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
-
-
-
-
-
- private static final int STUDENT = 1;
- private static final int STUDENTS = 2;
-
- static {
- URI_MATCHER.addURI("com.android.contentproviderdemo.StudentProvider",
- "student", STUDENTS);
- URI_MATCHER.addURI("com.android.contentproviderdemo.StudentProvider",
- "student/#", STUDENT);
- }
-
- public StudentProvider() {
-
- }
-
- @Override
- public boolean onCreate() {
-
- helper = new DBOpenHelper(getContext());
- return true;
- }
-
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- Cursor cursor = null;
- try {
- SQLiteDatabase databse = helper.getReadableDatabase();
- int flag = URI_MATCHER.match(uri);
- switch (flag) {
- case STUDENT:
- long id = ContentUris.parseId(uri);
- String where_value = " id = " + id;
- if (selection != null && !selection.equals("")) {
- where_value += " and " + selection;
- }
-
- cursor = databse.query("student", null, where_value, selectionArgs, null, null,
- null, null);
- break;
-
- case STUDENTS:
- cursor = databse.query("student", null, selection, selectionArgs, null, null,
- null, null);
- break;
- }
- } catch (Exception e) {
-
- }
- return cursor;
- }
-
-
-
-
-
-
-
- @Override
- public String getType(Uri uri) {
- int flag = URI_MATCHER.match(uri);
- switch (flag) {
- case STUDENT:
- return "vnd.android.cursor.item";
- case STUDENTS:
- return "vnd.android.cursor.dir/";
- }
- return null;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- Uri resultUri = null;
-
-
-
-
- int flag = URI_MATCHER.match(uri);
- switch (flag) {
- case STUDENTS:
- SQLiteDatabase database = helper.getWritableDatabase();
-
-
- long id = database.insert("student", null, values);
- resultUri = ContentUris.withAppendedId(uri, id);
- break;
- }
- Log.i(TAG, "ahuier----->" + resultUri.toString());
-
- return resultUri;
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- int count = -1;
- try {
- int flag = URI_MATCHER.match(uri);
- SQLiteDatabase database = helper.getWritableDatabase();
- switch (flag) {
- case STUDENT:
-
-
-
-
-
- long id = ContentUris.parseId(uri);
- String where_value = " id = " + id;
- if (selection != null && !selection.equals("")) {
- where_value += " and " + selection;
- }
-
- count = database.delete("student", where_value, selectionArgs);
- break;
-
- case STUDENTS:
-
-
- count = database.delete("studuent", selection, selectionArgs);
- break;
- }
- } catch (Exception e) {
-
- }
- return count;
- }
-
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- int count = -1;
- try {
-
- SQLiteDatabase database = helper.getWritableDatabase();
- long id = ContentUris.parseId(uri);
- int flag = URI_MATCHER.match(uri);
- switch (flag) {
- case STUDENT:
- String where_value = " id = " + id;
- if (selection != null && !selection.equals("")) {
- where_value += " and " + selection;
- }
- count = database.update("student", values, where_value, selectionArgs);
- break;
-
- case STUDENTS:
-
- break;
- }
- } catch (Exception e) {
-
- }
- return count;
- }
-
- }
4) MainActivity.java 界面程序代码,主要是作为 Content Resolver 代码解析者。跨应用操作数据库也可以用这个代码来使用的
- package com.android.contentproviderdemo;
-
- import android.net.Uri;
- import android.os.Bundle;
- import android.app.Activity;
- import android.content.ContentResolver;
- import android.content.ContentValues;
- import android.database.Cursor;
- import android.util.Log;
- import android.view.Menu;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
-
- public class MainActivity extends Activity {
-
- private static final String TAG = "MainActivity";
- private Button button1, button2, button3, button4, button5;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initComponent();
-
- button1.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- DBOpenHelper helper = new DBOpenHelper(MainActivity.this);
-
- helper.getWritableDatabase();
- }
- });
-
-
- button2.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- MainActivity.this.insert();
- }
- });
-
-
- button3.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- MainActivity.this.delete();
- }
- });
-
-
- button4.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- MainActivity.this.update();
- }
- });
-
-
- button5.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- MainActivity.this.query();
- }
- });
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
-
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
-
- private void initComponent(){
- button1 = (Button) findViewById(R.id.button1);
- button2 = (Button) findViewById(R.id.button2);
- button3 = (Button) findViewById(R.id.button3);
- button4 = (Button) findViewById(R.id.button4);
- button5 = (Button) findViewById(R.id.button5);
- }
-
- private void insert(){
-
-
- ContentResolver contentResolver = MainActivity.this.getContentResolver();
-
-
-
-
-
- Uri uri = Uri.parse("content://com.android.contentproviderdemo.StudentProvider/student");
- ContentValues values = new ContentValues();
- values.put("name", "AHuier");
- values.put("address", "XIAMEN");
- contentResolver.insert(uri, values);
- }
-
- private void delete() {
- ContentResolver contentResolver = MainActivity.this.getContentResolver();
-
-
-
-
- Uri uri = Uri.
- parse("content://com.android.contentproviderdemo.StudentProvider/student/1");
- contentResolver.delete(uri, null, null);
- }
-
- private void update() {
- ContentResolver contentResolver = MainActivity.this.getContentResolver();
- Uri uri = Uri.
- parse("content://com.android.contentproviderdemo.StudentProvider/student/2");
- ContentValues values = new ContentValues();
- values.put("name", "HUI");
- values.put("address", "Beijing");
- contentResolver.update(uri, values, null, null);
- }
-
-
- private void query() {
- ContentResolver contentResolver = MainActivity.this.getContentResolver();
-
-
- Uri uri = Uri.parse("content://com.android.contentproviderdemo.StudentProvider/student/2");
-
- Cursor cursor = contentResolver.query(uri, null, null, null, null);
- while(cursor.moveToNext()){
- Log.i(TAG, "ahuier---->" + cursor.getString(cursor.getColumnIndex("name")));
- }
- }
- }
4. 程序实现结果
1). 程序主界面
![](https://img-blog.csdn.net/20130921231411328?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWh1aWVy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
2). 往数据插入3个数据
3). 删除 id = 1 的数据
4). 修改 id = 2 的数据
3). 查询 id = 2 的名称
5. 后续
如何来证明其实跨应用进行通信呢?
另外再写一个应用,操作数据库的方式与上述代码的中的 MainActivity.java 方式类似,也是作为 Content Resolver 解析者的使用
详情参考 : http://developer.android.com/guide/topics/providers/content-providers.html