ContentProvider的使用

  为了在应用程序之间交换数据,Android提供了ContentProvider,ContentProvider是不同应用程序之间进行数据交换的标准API,当一个应用程序需要把自己的数据暴露给其他应用程序时,该应用程序就可通过提供Contentprovider来实现;其他应用程序就可通过ContentResolver来操作ContentProvider暴露的数据。

  ContentProvider是以某种Uri的形式对外提供数据,允许其他应用访问或修改数据;其他应用程序使用ContentResolver根据Uri去访问操作指定数据。使用ContentProvider的步骤如下(假设B应用程序要使用A应用程序中的数据):

1、在A应用程序中的AndroidManifest.xml文件里的application节点里添加以下代码:

1 <provider
2             android:name="com.gnnuit.provider.PersonProvider"
3             android:authorities="com.gnnuit.provider.PersonProvider" >
4 </provider>

  其中,android:name是自己编写的provider类的全名;android:authorities是外界访问的名字,就相当于为该ContentProvider指定域名。

2、在A应用程序里新建一个PersonProvider类使其继承ContentProvider基类。

  为了确定ContentProvider实际能处理的Uri,以及确定每个方法中Uri参数所操作的数据,Android系统提供了UriMatcher工具类。UriMatcher工具类主要提供了以下两个方法:

(1)void arrURI(String authority,String path,int code):该方法用于向UriMatcher对象注册Uri。其中authority和path组合成一个Uri,而code则代表Uri对应的标识码。

(2)int match(Uri uri):根据前面注册的Uri来判断指定Uri对应的标识码。如果找不到匹配的标识码,该方法将会返回-1。源码如下:

  1 package com.gnnuit.provider;
  2 
  3 import com.gnnuit.dao.PersonDao;
  4 import com.gnnuit.db.MyDbHelper;
  5 
  6 import android.content.ContentProvider;
  7 import android.content.ContentValues;
  8 import android.content.UriMatcher;
  9 import android.database.Cursor;
 10 import android.database.sqlite.SQLiteDatabase;
 11 import android.net.Uri;
 12 import android.util.Log;
 13 
 14 public class PersonProvider extends ContentProvider {
 15     private static final int ALL_PERSONS = 1;
 16     private static final int PERSON = 2;
 17     private static final int HAHA = 3;
 18     private static final int INSERT = 4;
 19     private static final int DELETE = 5;
 20     private static final int UPDATE = 6;
 21     private static final String TAG = "PersonProvider";
 22     private MyDbHelper dbHelper;
 23     // 创建了一个路径的识别器 uriMatcher 默认的返回值,如果没有找到匹配的类型 返回 -1;
 24     private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
 25     static {
 26         // 指定一个路径的匹配规则
 27         // 如果路径 满足 content://com.gnnuit.provider.PersonProvider/persons 返回值就是(
 28         // ALL_PERSONS) 1
 29         matcher.addURI("com.gnnuit.provider.PersonProvider", "persons",
 30                 ALL_PERSONS);
 31         // 如果路径 满足 content://com.gnnuit.provider.PersonProvider/person/10 返回值就是(
 32         // PERSON) 2
 33         matcher.addURI("com.gnnuit.provider.PersonProvider", "person/#", PERSON);
 34         matcher.addURI("com.gnnuit.provider.PersonProvider", "haha", HAHA);
 35         matcher.addURI("com.gnnuit.provider.PersonProvider", "insert", INSERT);
 36         matcher.addURI("com.gnnuit.provider.PersonProvider", "delete", DELETE);
 37         matcher.addURI("com.gnnuit.provider.PersonProvider", "update", UPDATE);
 38     }
 39 
 40     /**
 41      * PeronProvder 内容提供者第一次被创建的时候 调用的方法
 42      */
 43     @Override
 44     public boolean onCreate() {
 45         dbHelper = new MyDbHelper(getContext());
 46         return false;
 47     }
 48 
 49     @Override
 50     public Cursor query(Uri uri, String[] projection, String selection,
 51             String[] selectionArgs, String sortOrder) {
 52         int result = matcher.match(uri);
 53         switch (result) {
 54         case ALL_PERSONS:
 55             PersonDao dao = new PersonDao(getContext());
 56             return dao.getAllByCursor();
 57         case PERSON:
 58             SQLiteDatabase db = dbHelper.getReadableDatabase();
 59             if (db.isOpen()) {
 60                 Cursor cursor = db.query("person", projection, selection,
 61                         selectionArgs, null, null, null);
 62                 return cursor;
 63             }
 64         case HAHA:
 65             Log.i(TAG, "我是哈哈");
 66             return null;
 67         default:
 68             throw new IllegalArgumentException("URI不合法");
 69         }
 70     }
 71 
 72     /**
 73      * 有的时候 我们需要知道内容提供者返回的数据类型 知道返回的数据 是一个集合呀 还是一个单独的条目
 74      * 
 75      * 有的时候 告诉调用者 返回的数据是什么样的类型 MIME的数据类型
 76      */
 77     @Override
 78     public String getType(Uri uri) {
 79         int result = matcher.match(uri);
 80         switch (result) {
 81         // 符合 content://com.gnnuit.provider.PersonProvider/persons 代表的返回所有的数据
 82         case ALL_PERSONS:
 83             return "vnd.android.cursor.dir/people";
 84             // content://com.gnnuit.provider.PersonProvider/person/10
 85         case PERSON:
 86             return "vnd.android.cursor.item/people";
 87         default:
 88             return null;
 89         }
 90     }
 91 
 92     @Override
 93     public Uri insert(Uri uri, ContentValues values) {
 94         int result = matcher.match(uri);
 95         if (result == INSERT) {
 96             SQLiteDatabase db = dbHelper.getWritableDatabase();
 97             db.insert("person", null, values);
 98             // 当数据发生改变的时候
 99             getContext().getContentResolver().notifyChange(uri, null);
100             return uri;
101         } else {
102             throw new IllegalArgumentException("URI不能被识别");
103         }
104     }
105 
106     @Override
107     public int delete(Uri uri, String selection, String[] selectionArgs) {
108         int result = matcher.match(uri);
109         if (result == DELETE) {
110             SQLiteDatabase db = dbHelper.getWritableDatabase();
111             // 当数据发生改变的时候
112             getContext().getContentResolver().notifyChange(uri, null);
113             return db.delete("person", selection, selectionArgs);
114         } else {
115             throw new IllegalArgumentException("URI不能被识别");
116         }
117     }
118 
119     @Override
120     public int update(Uri uri, ContentValues values, String selection,
121             String[] selectionArgs) {
122         int result = matcher.match(uri);
123         if (result == UPDATE) {
124             SQLiteDatabase db = dbHelper.getWritableDatabase();
125             // 当数据发生改变的时候
126             getContext().getContentResolver().notifyChange(uri, null);
127             return db.update("person", values, selection, selectionArgs);
128         } else {
129             throw new IllegalArgumentException("URI不能被识别");
130         }
131     }
132 
133 }

  public String getType(Uri uri):该方法用于返回当前Uri所代表的MIME类型。如果该Uri对应数据可能包括多条记录,那么MIME类型字符串应该以vnd.android.cursor.dir/开头;如果该Uri对应的数据只包含一条记录,那么返回MIME类型字符串应该以vnd.android.cursor.item/开头。

3、在B应用程序中使用,首先我们要得到一个ContentResolver对象,Context提供了getContentResolver()方法来获取ContentResolver对象。源码如下:

 1 package com.gnnuit.other;
 2 
 3 import android.net.Uri;
 4 import android.os.Bundle;
 5 import android.app.Activity;
 6 import android.content.ContentResolver;
 7 import android.database.Cursor;
 8 import android.view.Menu;
 9 
10 public class MainActivity extends Activity {
11 
12     @Override
13     protected void onCreate(Bundle savedInstanceState) {
14         super.onCreate(savedInstanceState);
15         setContentView(R.layout.activity_main);
16         ContentResolver resolver = getContentResolver();
17         Uri uri = Uri.parse("content://com.gnnuit.provider.PersonProvider/persons");
18         Cursor cursor = resolver.query(uri, null, null, null, null);
19         if (cursor != null) {
20             while (cursor.moveToNext()) {
21                 String name = cursor.getString(cursor.getColumnIndex("name"));
22                 String age = cursor.getString(cursor.getColumnIndex("age"));
23                 System.out.println("姓名:" + name + "年命:" + age);
24             }
25         } else {
26             System.out.println("cursor为空");
27         }
28     }
29 
30     @Override
31     public boolean onCreateOptionsMenu(Menu menu) {
32         // Inflate the menu; this adds items to the action bar if it is present.
33         getMenuInflater().inflate(R.menu.main, menu);
34         return true;
35     }
36 
37 }

 4、ContentProvider的Uri简介

  ContentProvider的Uri类似于HTTP的Uri,例如以下的Uri:

content://com.gnnuit.provider.personprovider/persons

  它可以分为以下三个部分:

(1)content://:这个部分是Android的ContentProvider规定的,就像http://一样。暴露ContentProvider、访问ContentProvider的协议默认是content://。

(2)com.gnnuit.provider.personprovider:这个部分是ContentProvider的authority。系统就是由这个部分来找到操作哪个ContentProvider。只要访问指定的ContentProvider,这个部分总是固定的。

(3)persons:资源部分,当访问者需要访问不同资源时,这个部分是动态改变的。

5、几种典型的Uri含义:

(1)content://com.gnnuit.provider.personprovider/persons

  此时它要访问的资源为persons,这意味着访问perosn数据中的所有记录。

(2)content://com.gnnuit.provider.personprovider/person/2

  此时它要访问的资源为person/2,这意味着访问person数据中ID为2的记录。

(3)content://com.gnnuit.provider.personprovider/person/2/name

  此时它要访问的资源为person/2/name,这意味着访问perosn数据中ID为2的记录的name字段。

(4)大部分ContentProvider所操作的数据都来自于数据库,但有时这些数据也可来自于文件、XML或网络等其他存储方式,此时的Uri可改为如下形式:

content://com.gnnuit.provider.personprovider/person/name/

  上面的Uri表示操作person节点下的name节点。

6、将一个字符串转化成Uri的方法:

  Uri uri=Uri.parse("content://com.gnnuit.provider.personprovider/persons");

原文地址:https://www.cnblogs.com/FlySheep/p/3452740.html