ContentProvider 数据供应器_读取联系人信息

Android 系统将所有数据都规定为对外私有,也就是无法直接访问应用程序之外的数据。如果需要访问其他应用程序的数据或向其他应用程序提供数据,就需要使用 ContentProvider(数据供应器)。该类位于 android.content 包中,为存储和获取数据提供了统一的接口。

Android 为常见的一些数据提供了默认的 ContentProvider,包括音频、视频、图片和通信录等,使用时需要得到相应访问的权限。 ContentProvider 常用方法说明:

1、Cursor  query(Uri  uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);   查询操作,通过 uri 查询数据,返回 Cursor (这个查询语法类似于 Hibernate)

2、Uri  insert(Uri uri, ContentValues values);  插入操作,将数据插入到 uri 指定内容,数据需要封装到 ContentValues 对象中。

3、int  update(Uri uri, ContentValues values, String selection, String[] selectionArgs);  更新操作。

4、int  delete(Uri uri, String selection, String[] selectionArgs);  删除操作。

外界程序在访问 ContentProvider 中的数据时,并不是进行直接操作,而是借助 ContentResolver 类,该类也位于 android.content 包中,多数方法都是由 Static final 修饰,它是作为一个工具类来使用的。

ContentResolver 对象可以通过 getContentResolver() 方法(Content 类的方法)得到,其中提供的方法与 ContentProvider 类中的方法对应。使用  ContentProvider 对象读取数据设计的类有 Uri(数据统一标志)、ContentResolver(读取数据的功能)、Cursor(包含结果数据的游标)。

1 ContentResolver cr = getContentResolver();
2 Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, data, null, null, null);

ContentResolver 类的 query 方法和 managedQuery 方法具有相同的参数要求,查询方法参数明显如下:

1、Uri  uri:待查询参数(Content Provider)的 Uri

2、String[] projection:需要查询的字段,相当于 Select 语句后面的字段信息

3、String  selection:查询的条件,相当于 WHERE 子句后面的条件

4、String[] selectionArgs:查询条件的值,给 WHERE 子句中的占位参数传值

5、String sortOrder:排序条件,相当于 Order by 子句。

ContactsContract.Data.CONTENT_URI 是联系人数据的 Uri,是系统级 Uri。data 数组保存需要查询的字段值,都引用了 ContactsContract.Data 类的属性。ContactsContract.Data.MIMETYPE 属性是标明该数据是何种类型的信息。Phone.CONTENT_ITEM_TYPE 即为电话号码。查询的结果会返回 Cursor 对象,即游标,可以移动,具有生命周期。

总之,使用 ContentProvider 查询其他程序中暴露的数据比较简单:

1、确定需要查询数据的 Uri(Adndroid 系统中有很多原生态的 Uri);

2、使用 ContentResolver 类中的 query 方法查询;

3、检索 Cursor,处理相应数据。

Uri 类位于 android.net 包中,代表了要操作的数据,主要包含两部分的信息:需要操作的 ContentProvider 与 ContentProvider 中的具体数据。一个 Uri 由以下几个部分构成:如

content://com.example.transportationprovider/trains/122

A:前缀标志,任何 Uri 都有一个固定的前缀,Content:// 标明这是 ContentProvider 中使用的 Uri。

B: 数据的权限标志,com.example.transportationprovider,要求唯一。

C: 路径标志,trains,代表 Uri 所要访问的具体数据表。

D: ID 信息,122,C 中数据表的某一个 ID 值。

联系人数据表的 Uri 是 ContactsContract.Data.CONTENT_URI 常量,对应的具体的 Uri 字符串是:content://com.android.contacts/data。说明要访问 data 表中的全部数据。如果改为:content://com.android.contacts/data/2,则表明访问 data 表中 ID 为 2 的那条记录。可以通过 Uri.parse(content://com.android.contacts/data) 来获得  ContactsContract.Data.CONTENT_URI 对象。

UriMatcher 类用于匹配 Uri 的检验,主要涉及方法 addURI(String authority, String path, int code) 和 match(Uri  uri)。

1 // 匹配检验
2         UriMatcher uMatcher = new UriMatcher(UriMatcher.NO_MATCH);
3         uMatcher.addURI("com.android.contacts", "data", 1);
4         int r = uMatcher.match(ContactsContract.Data.CONTENT_URI);

创建 UriMatcher 对象,传入常量 NO_MATCH,当匹配不成功时会返回该常量的值。使用 addURI 方法添加匹配样式,相当于模板,供待检验的 Uri 与此对比,可以多次调用此方法,添加多个模板。该方法有三个参数:

1、Uri 的数据权限;

2、路径标识,可以使用通配符(*用于通配文本,#用于通配数字);

3、匹配成功时的返回值,通过与此值对比,可以判定是否匹配成功。

match 方法用于匹配 Uri,若匹配成功,返回 addURI 方法中的第三个参数,若不成功,返回构造 UriMatch 时传入的参数。

ContentUris 类用于操作 Uri 路径后面的 ID 部分,它有如下两个比较实用的方法。

1、static Uri withAppendedId(Uri contentUri, long id),向 Uri 路径后面追加 id;

2、static long parseId(Uri contentUri),获取 Uri 中的 id 值。

开启权限

<uses-permission android:name="android.permission.READ_CONTACTS"/>

 1 public class MainActivity extends Activity {
 2     Button bt;
 3     TextView tv;
 4     
 5     @Override
 6     public void onCreate(Bundle savedInstanceState) {
 7         super.onCreate(savedInstanceState);
 8         
 9         setContentView(R.layout.main);
10         bt = (Button) findViewById(R.id.bt);
11         tv = (TextView) findViewById(R.id.tv);
12         bt.setOnClickListener(new OnClickListener(){
13             
14             @Override
15             public void onClick(View v) {
16                 //显示所有联系人
17                 showAllContacts();
18             }
19         });
20     }
21     
22     // 查询所有联系人信息
23     public void showAllContacts(){
24         
25         // 构造需要查询信息的字段
26         String data[] = {ContactsContract.Data._ID,    // 联系人 ID 唯一、必须
27                 ContactsContract.Data.DISPLAY_NAME,    // 联系人名
28                 ContactsContract.Data.MIMETYPE,
29                 ContactsContract.Data.DATA1};    //电话
30         
31         // 查询指定资源的数据
32         //Cursor cursor = managedQuery(ContactsContract.Data.CONTENT_URI, data, null, null, null);
33         ContentResolver cr = getContentResolver();
34         Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, data, null, null, null);
35         Log.i("Tag", ContactsContract.Data.CONTENT_URI.toString());
36         
37         // 匹配检验
38         UriMatcher uMatcher = new UriMatcher(UriMatcher.NO_MATCH);
39         uMatcher.addURI("com.android.contacts", "data", 1);
40         int r = uMatcher.match(ContactsContract.Data.CONTENT_URI);
41         Log.i("Tag", "匹配结果:" + r);
42         
43         cursor.moveToFirst();
44         StringBuffer txt = new StringBuffer();
45         while(!cursor.isAfterLast()){
46             Log.i("Tag", cursor.getString(2));
47             // 只显示有电话号码的联系人
48             if(cursor.getString(2).equalsIgnoreCase(Phone.CONTENT_ITEM_TYPE)){
49                 txt.append("ID: "+cursor.getString(0)+"\t");
50                 txt.append("Name: "+cursor.getString(1)+"\t");
51                 txt.append("Phone: "+cursor.getString(3));
52                 txt.append('\n');
53             }
54             cursor.moveToNext();
55         }
56         tv.setText(txt);    
57     }
58 }

 

posted @ 2015-05-26 19:16  壬子木  阅读(200)  评论(0)    收藏  举报