一、Content Provider基本概念
1、ContentProvider为存储和获取数据提供了统一的接口。ContentProvide对数据进行封装,不用关心数据存储的细节。使用表的形式来组织数据。
2、使用ContentProvider可以在不同的应用程序之间共享数据。
3、Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。
ContentProvider所提供的函数: query(),insert(),update(),delete(),getType(),onCreate()等。
二、URI(统一资源标识符)的使用方法
为系统的每一个资源给其一个名字,比方说通话记录。
1、每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。
2、Android所提供的ContentProvider都存放在android.provider包中。 将其分为A,B,C,D 4个部分:
A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;"content://"
B:URI 的标识,它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的 类名。这个标识在元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称;"content://hx.android.text.myprovider"
C:路径,通俗的讲就是数据库中要操作的表的名字
D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部
Uri写法1
Uri uri = Uri.parsecontent://media/internal/images") 这个URI将返回设备上存储的所有图片
content://contacts/people/ 这个URI将返回设备上的所有联系人信息 content://contacts/people/45 这个URI返回单个结果(联系人信息中ID为45的联系人记录)Uri写法2
Uri person = ContentUris.withAppendedId(People.CONTENT_URI, 45);
然后执行数据查询: Cursor cur = managedQuery(person, null, null, null);
这个查询返回一个包含所有数据字段的游标,我们可以通过迭代这个游标来获取所有的数据:
三、ContentProvider的使用
实现: 应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法
自己实现ContentProvider不常见,因为可能不需要和别的应用程序交换数据。
因此下面主要介绍ContentProvider的使用
- 从Android 2.0 SDK开始有关联系人provider的类从android.provider.Contacts变成了android.provider.ContactsContract
- ContactsContract的子类ContactsContract.Contacts是一张表,代表了所有联系人的统计信息。比如联系人ID(—ID),查询键(LOOKUP_KEY),联系人的姓名(DISPLAY_NAME_PRIMARY),头像的id(PHOTO_ID)以及群组的id等等
- 在新的Contacts API中,联系人数据被安排三个主要的表中:contacts, raw contacts and data. 结构如下图所示:
一个contact(联系人)记录关联一个或多个RawContact(联系人来源,如Gmail)记录,每个RawContact记录又关联多个data(email, phone number等等)记录
package com.example.manhua;import java.util.ArrayList;import android.app.ListActivity;import android.database.Cursor;import android.net.Uri;import android.os.Bundle;import android.provider.ContactsContract;import android.widget.ArrayAdapter;import android.widget.ListView;public class MainActivity extends ListActivity { /* * ListActivity的默认布局由一个位于屏幕中心的全屏列表构成。 * 如果你不想使用默认的布局,可以在onCreate()方法中通过setContentView()方法设定你自己的布局。 * 如果指定你自己定制的布局,你的布局中必须包含一个id为"@id/android:list"的ListView。 * 若你还指定了一个id为"@id/android:empty"的view,当ListView中没有数据要显示时, * 这个view就会被显示,同时 ListView会被隐藏。 * */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); displayRecords(); } //private void displayRecords() { Uri contactsUri = ContactsContract.Contacts.CONTENT_URI; // 该数组中包含了所有要返回的字段 String proj1[] = new String[] { ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.HAS_PHONE_NUMBER , ContactsContract.Contacts.LOOKUP_KEY}; // declare a ArrayList object to store the data that will present to the // user Cursor curContacts = getContentResolver().query(contactsUri, proj1, null, null, null); ArrayList contactsList = new ArrayList (); String allPhoneNo = ""; if (curContacts.getCount() > 0) { while (curContacts.moveToNext()) { // get all the phone numbers if exist if (curContacts.getInt(1) > 0) { allPhoneNo = getAllPhoneNumbers(curContacts.getString(2)); } contactsList.add(curContacts.getString(0) + " , " + allPhoneNo); allPhoneNo = ""; } } // binding the data to ListView setListAdapter(new ArrayAdapter (this, android.R.layout.simple_list_item_1, contactsList)); ListView lv = getListView(); lv.setTextFilterEnabled(true); } /** * Get all the phone numbers of a specific contact person * * @param lookUp_Key * lookUp key for a specific contact * @return a string containing all the phone numbers */ public String getAllPhoneNumbers(String lookUp_Key) { String allPhoneNo = ""; // Phone info are stored in the ContactsContract.Data table Uri phoneUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; String[] proj2 = { ContactsContract.CommonDataKinds.Phone.NUMBER }; // using lookUp key to search the phone numbers String selection = ContactsContract.Data.LOOKUP_KEY + "=?"; Cursor cur = getContentResolver().query(phoneUri, proj2, selection, new String[] { lookUp_Key }, null); while (cur.moveToNext()) { allPhoneNo += cur.getString(0) + " "; } return allPhoneNo; }}
由于读取联系人比较的占用资源,为了提高用户的体验度。考虑将读取的过程放在线程里完成,推荐使用AsyncTask类