【摘】ContentProvider总结

  ContentProvider一般译作内容提供者,官方文档中的解释:它用来管理结构化数据的访问。通过它我们可以共享自己应用中的数据,或者访问别的应用提供的数据,比如‘联系人’应用就实现了ContentProvider,通过它提供的ContentProvider我们可以查询、删除、更新联系人数据。

ContentProvider简介

 ContentProvider是不同应用程序之间进行数据交换的标准API,ContentProvider以URI的形式对外提供数据,允许其他应用访问或修改数据;其他应用程序使用ContentResolver根据URI去访问\操作指定的数据。ContentProvider可以看作是一个网站,用来提供各种数据;ContentResolver则可当成浏览器。我们访问某个网站其实就是想获取那个网站上的数据。而且我们是通过浏览器与网站交互的。

开发步骤

1.从ContentProvider派生出一个子类,并重写如下方法: 

   public boolean onCreate() 该方法在ContentProvider创建后就会被调用, Android在系统启动时就会创建ContentProvider 。

  public Uri insert(Uri uri, ContentValues values) 该方法用于供外部应用往ContentProvider添加数据。

  public int delete(Uri uri, String selection, String[] selectionArgs) 该方法用于供外部应用从ContentProvider删除数据。

  public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 该方法用于供外部应用更新ContentProvider中的数据。

  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 该方法用于供外部应用从ContentProvider中获取数据。

  public String getType(Uri uri) 该方法用于返回当前Url所代表数据的MIME类型。

如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头,例如:要得到person记录的Uri为content://cn.itcast.provider.personprovider/person,那么返回的MIME类型字符串应该为:“vnd.android.cursor.dir/person”。如果要操作的数据属于单一数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,例如:得到id为10的person记录,Uri为content://cn.itcast.provider.personprovider/person/10,那么返回的MIME类型字符串应该为:“vnd.android.cursor.item/person”。

2.在AndroidManifest.xml中注册之,和其它组件的注册过程类似。

<!-- 注册一个ContentProvider -->
        <provider android:name=".ExampleProvider" 
            android:authorities="com.example.provider"/>

 其中authorities属性就相当于网站的url。

使用ContentResolver操作ContentProvider中的数据

当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver 类提供了与ContentProvider类相同签名的四个方法:

  public Uri insert(Uri uri, ContentValues values) 该方法用于往ContentProvider添加数据。

  public int delete(Uri uri, String selection, String[] selectionArgs) 该方法用于从ContentProvider删除数据。

  public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 该方法用于更新ContentProvider中的数据。

  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 该方法用于从ContentProvider中获取数据。

这些方法的第一个参数为Uri,代表要操作的是哪个ContentProvider和对其中的什么数据进行操作,假设给定的是: Uri.parse(“content://cn.itcast.provider.personprovider/person/10”),那么将会对主机名为cn.itcast.provider.personprovider的ContentProvider进行操作,操作的数据为person表中id为10的记录。

URI介绍:

  Uri代表了要操作的数据,Uri主要包含了两部分信息:1》需要操作的ContentProvider ,2》对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:

 

 ContentProvider(内容提供者)的scheme已经由Android所规定, scheme为:content://

主机名(或叫Authority)用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。

路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:

要操作person表中id为10的记录,可以构建这样的路径:/person/10

要操作person表中id为10的记录的name字段, person/10/name

要操作person表中的所有记录,可以构建这样的路径:/person

要操作xxx表中的记录,可以构建这样的路径:/xxx

当然要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:

要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name

如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:

Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person")

UriMatcher类使用介绍

因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris 。掌握它们的使用,会便于我们的开发工作。 UriMatcher类用于匹配Uri,它的用法如下:

首先第一步把你需要匹配Uri路径全部给注册上,如下:

/常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://cn.itcast.provider.personprovider/person路径,返回匹配码为1
sMatcher.addURI(“cn.itcast.provider.personprovider”, “person”, 1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配content://cn.itcast.provider.personprovider/person/230路径,返回匹配码为2
sMatcher.addURI(“cn.itcast.provider.personprovider”, “person/#”, 2);//#号为通配符
switch (sMatcher.match(Uri.parse("content://cn.itcast.provider.personprovider/person/10"))) { 
   case 1
    break;
   case 2
    break;
   default://不匹配
    break;
}

注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://cn.itcast.provider.personprovider/person路径,返回的匹配码为1

ContentUris类使用介绍

ContentUris类用于获取Uri路径后面的ID部分,它有两个比较实用的方法:

withAppendedId(uri, id)用于为路径加上ID部分:

Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person")

Uri resultUri = ContentUris.withAppendedId(uri, 10); //生成后的Uri为:content://cn.itcast.provider.personprovider/person/10

parseId(uri)方法用于从路径中获取ID部分: Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person/10")

long personid = ContentUris.parseId(uri);//获取的结果为:10

 

 示例:

  1 package org.crazyit.content;
  2 
  3 import java.util.ArrayList;
  4 
  5 import android.app.Activity;
  6 import android.app.AlertDialog;
  7 import android.content.ContentUris;
  8 import android.content.ContentValues;
  9 import android.database.Cursor;
 10 import android.net.Uri;
 11 import android.os.Bundle;
 12 import android.provider.ContactsContract;
 13 import android.provider.ContactsContract.CommonDataKinds.Email;
 14 import android.provider.ContactsContract.CommonDataKinds.Phone;
 15 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 16 import android.provider.ContactsContract.RawContacts;
 17 import android.provider.ContactsContract.RawContacts.Data;
 18 import android.view.Gravity;
 19 import android.view.View;
 20 import android.view.View.OnClickListener;
 21 import android.view.ViewGroup;
 22 import android.widget.AbsListView;
 23 import android.widget.BaseExpandableListAdapter;
 24 import android.widget.Button;
 25 import android.widget.EditText;
 26 import android.widget.ExpandableListAdapter;
 27 import android.widget.ExpandableListView;
 28 import android.widget.TextView;
 29 import android.widget.Toast;
 30 
 31 public class ContactProviderTest extends Activity {
 32     Button search;
 33     Button add;
 34 
 35     @Override
 36     public void onCreate(Bundle savedInstanceState) {
 37         super.onCreate(savedInstanceState);
 38         setContentView(R.layout.main);
 39         // 获取系统界面中查找、添加两个按钮
 40         search = (Button) findViewById(R.id.search);
 41         add = (Button) findViewById(R.id.add);
 42         search.setOnClickListener(new OnClickListener() {
 43             @Override
 44             public void onClick(View source) {
 45                 // 定义两个List来封装系统的联系人信息、指定联系人的电话号码、Email等详情
 46                 final ArrayList<String> names = new ArrayList<String>();
 47                 final ArrayList<ArrayList<String>> details = new ArrayList<ArrayList<String>>();
 48                 // 使用ContentResolver查找联系人数据
 49                 Cursor cursor = getContentResolver().query(
 50                         ContactsContract.Contacts.CONTENT_URI, null, null,
 51                         null, null);
 52                 // 遍历查询结果,获取系统中所有联系人
 53                 while (cursor.moveToNext()) {
 54                     // 获取联系人ID
 55                     String contactId = cursor.getString(cursor
 56                             .getColumnIndex(ContactsContract.Contacts._ID));
 57                     // 获取联系人的名字
 58                     String name = cursor.getString(cursor
 59                             .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
 60                     names.add(name);
 61                     // 使用ContentResolver查找联系人的电话号码
 62                     Cursor phones = getContentResolver().query(
 63                             ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
 64                             null,
 65                             ContactsContract.CommonDataKinds.Phone.CONTACT_ID
 66                                     + " = ?", new String[] { contactId }, null);
 67                     ArrayList<String> detail = new ArrayList<String>();
 68                     // 遍历查询结果,获取该联系人的多个电话号码
 69                     while (phones.moveToNext()) {
 70                         // 获取查询结果中电话号码列中数据。
 71                         String phoneNumber = phones.getString(phones
 72                                 .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
 73                         detail.add("电话号码:" + phoneNumber);
 74                     }
 75                     phones.close();
 76                     // 使用ContentResolver查找联系人的Email地址
 77                     Cursor emails = getContentResolver().query(
 78                             ContactsContract.CommonDataKinds.Email.CONTENT_URI,
 79                             null,
 80                             ContactsContract.CommonDataKinds.Email.CONTACT_ID
 81                                     + " = " + contactId, null, null);
 82                     // 遍历查询结果,获取该联系人的多个Email地址
 83                     while (emails.moveToNext()) {
 84                         // 获取查询结果中Email地址列中数据。
 85                         String emailAddress = emails.getString(emails
 86                                 .getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
 87                         detail.add("邮件地址:" + emailAddress);
 88                     }
 89                     emails.close();
 90                     details.add(detail);
 91                 }
 92                 cursor.close();
 93                 // 加载result.xml界面布局代表的视图
 94                 View resultDialog = getLayoutInflater().inflate(
 95                         R.layout.result, null);
 96                 // 获取resultDialog中ID为list的ExpandableListView
 97                 ExpandableListView list = (ExpandableListView) resultDialog
 98                         .findViewById(R.id.list);
 99                 // 创建一个ExpandableListAdapter对象
100                 ExpandableListAdapter adapter = new BaseExpandableListAdapter() {
101                     // 获取指定组位置、指定子列表项处的子列表项数据
102                     @Override
103                     public Object getChild(int groupPosition, int childPosition) {
104                         return details.get(groupPosition).get(childPosition);
105                     }
106 
107                     @Override
108                     public long getChildId(int groupPosition, int childPosition) {
109                         return childPosition;
110                     }
111 
112                     @Override
113                     public int getChildrenCount(int groupPosition) {
114                         return details.get(groupPosition).size();
115                     }
116 
117                     private TextView getTextView() {
118                         AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
119                                 ViewGroup.LayoutParams.FILL_PARENT, 64);
120                         TextView textView = new TextView(
121                                 ContactProviderTest.this);
122                         textView.setLayoutParams(lp);
123                         textView.setGravity(Gravity.CENTER_VERTICAL
124                                 | Gravity.LEFT);
125                         textView.setPadding(36, 0, 0, 0);
126                         textView.setTextSize(20);
127                         return textView;
128                     }
129 
130                     // 该方法决定每个子选项的外观
131                     @Override
132                     public View getChildView(int groupPosition,
133                             int childPosition, boolean isLastChild,
134                             View convertView, ViewGroup parent) {
135                         TextView textView = getTextView();
136                         textView.setText(getChild(groupPosition, childPosition)
137                                 .toString());
138                         return textView;
139                     }
140 
141                     // 获取指定组位置处的组数据
142                     @Override
143                     public Object getGroup(int groupPosition) {
144                         return names.get(groupPosition);
145                     }
146 
147                     @Override
148                     public int getGroupCount() {
149                         return names.size();
150                     }
151 
152                     @Override
153                     public long getGroupId(int groupPosition) {
154                         return groupPosition;
155                     }
156 
157                     // 该方法决定每个组选项的外观
158                     @Override
159                     public View getGroupView(int groupPosition,
160                             boolean isExpanded, View convertView,
161                             ViewGroup parent) {
162                         TextView textView = getTextView();
163                         textView.setText(getGroup(groupPosition).toString());
164                         return textView;
165                     }
166 
167                     @Override
168                     public boolean isChildSelectable(int groupPosition,
169                             int childPosition) {
170                         return true;
171                     }
172 
173                     @Override
174                     public boolean hasStableIds() {
175                         return true;
176                     }
177                 };
178                 // 为ExpandableListView设置Adapter对象
179                 list.setAdapter(adapter);
180                 // 使用对话框来显示查询结果。
181                 new AlertDialog.Builder(ContactProviderTest.this)
182                         .setView(resultDialog).setPositiveButton("确定", null)
183                         .show();
184             }
185         });
186         // 为add按钮的单击事件绑定监听器
187         add.setOnClickListener(new OnClickListener() {
188             @Override
189             public void onClick(View v) {
190                 // 获取程序界面中的3个文本框
191                 String name = ((EditText) findViewById(R.id.name)).getText()
192                         .toString();
193                 String phone = ((EditText) findViewById(R.id.phone)).getText()
194                         .toString();
195                 String email = ((EditText) findViewById(R.id.email)).getText()
196                         .toString();
197                 // 创建一个空的ContentValues
198                 ContentValues values = new ContentValues();
199                 // 向RawContacts.CONTENT_URI执行一个空值插入,
200                 // 目的是获取系统返回的rawContactId
201                 Uri rawContactUri = getContentResolver().insert(
202                         RawContacts.CONTENT_URI, values);
203                 long rawContactId = ContentUris.parseId(rawContactUri);
204 
205                 values.clear();
206                 values.put(Data.RAW_CONTACT_ID, rawContactId);
207                 // 设置内容类型
208                 values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
209                 // 设置联系人名字
210                 values.put(StructuredName.GIVEN_NAME, name);
211                 // 向联系人URI添加联系人名字
212                 getContentResolver().insert(
213                         android.provider.ContactsContract.Data.CONTENT_URI,
214                         values);
215 
216                 values.clear();
217                 values.put(Data.RAW_CONTACT_ID, rawContactId);
218                 values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
219                 // 设置联系人的电话号码
220                 values.put(Phone.NUMBER, phone);
221                 // 设置电话类型
222                 values.put(Phone.TYPE, Phone.TYPE_MOBILE);
223                 // 向联系人电话号码URI添加电话号码
224                 getContentResolver().insert(
225                         android.provider.ContactsContract.Data.CONTENT_URI,
226                         values);
227 
228                 values.clear();
229                 values.put(Data.RAW_CONTACT_ID, rawContactId);
230                 values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
231                 // 设置联系人的Email地址
232                 values.put(Email.DATA, email);
233                 // 设置该电子邮件的类型
234                 values.put(Email.TYPE, Email.TYPE_WORK);
235                 // 向联系人Email URI添加Email数据
236                 getContentResolver().insert(
237                         android.provider.ContactsContract.Data.CONTENT_URI,
238                         values);
239 
240                 Toast.makeText(ContactProviderTest.this, "联系人数据添加成功", 8000)
241                         .show();
242             }
243         });
244     }
245 }
View Code

 

PS:最近几天,基本上把官方文档中关于ContentProvider的部分看完了。可懒得自己写总结了,以上内容基本上全部来自黎活明的android培训课件。

posted @ 2013-05-25 18:29  g.hui  阅读(184)  评论(0编辑  收藏  举报