这部分展示怎么获得一个详细的联系人信息,比如email,电话号码等。你可以显示全部信息,也可以显示部分信息,比如单单email。
这里假设你有一列ContactsContract.Contacts。
Retrieve all Details for a Contact (获得联系人所有的详细信息)
通过在ContactsContract.Data表格中查找包含列LOOKUP_KEY中匹配的行,返回查找的信息已获取联系人详细信息。由于ContactsContract.Contacts表格和ContactsContract.Data表格之间已经关联号,所以对应的列存在ContactsContract.Data中。在Retriving Contact Names中有详细介绍了LOOKUP_KEY
注意:获得一个联系人的详细信息会影响设备的性能,因为需要从ContactsContract.Data表格中获得所有的列,在实际应用中要考虑这个影响。
Request permissions (请求权限)
为了从Contact Provider读取数据,必须具备READ_CONTACTS的权限。通过下面代码来获得权限:
<uses-permission android:name="android.permission.READ_CONTACTS" />
Set up a projection (定义一个投射数组)
每行中可以有多个列,数据根据它们的类型位于不同的列中。为了保证获得所有列的数据类型,你必须在你的投射数据中添加所有的列名。如果你将查询结果用Cursor与ListView绑定,记得要获取联系人的Data._ID,不然无法绑定。为了保证可以分辨出每行的数据类型,添加Data.MIMETYPE。
private static final String PROJECTION =
{
Data._ID,
Data.MIMETYPE,
Data.DATA1,
Data.DATA2,
Data.DATA3,
Data.DATA4,
Data.DATA5,
Data.DATA6,
Data.DATA7,
Data.DATA8,
Data.DATA9,
Data.DATA10,
Data.DATA11,
Data.DATA12,
Data.DATA13,
Data.DATA14,
Data.DATA15
};
这个投射数组可以获得ContactsContract.Data的所有列,这些列名都定义在ContactsContract.Data中。
当然你也可以使用其他定义在ContactsContract.Data继承子类中。注意列SYN1到SYN2是为了用于同步的adapter,所以它们的数据没用。
Define the selection criteria (定义选择规则)
定义一个选择规则常量,一个数据用来保存选择的参数,一个变量用来保存选择的值。通过Contacts.LOOKUP_KEY列来查找联系人。
// Defines the selection clause
private static final String SELECTION = Data.LOOKUP_KEY + " = ?";
// Defines the array to hold the search criteria
private String[] mSelectionArgs = { "" };
/*
* Defines a variable to contain the selection value. Once you
* have the Cursor from the Contacts table, and you've selected
* the desired row, move the row's LOOKUP_KEY value into this
* variable.
*/
private String mLookupKey;
在你的选择表达式中添加”?“以便查找的结果是有绑定生成而不是SQL汇集的。这样可以消除其它SQL无用信息。
Define the sort order (定义排序顺序)
定义在结果的Cursor的排序顺序。为了保证所有相同的数据类型的行都在一块,可以以Data.MIMETYPE排序。这样可以使得所有的email行都在一块,所有的电话行都在一块等。
/*
* Defines a string that specifies a sort order of MIME type
*/
private static final String SORT_ORDER = Data.MIMETYPE;
注意:一些数据类型不适用subtype,所以不同意subtype排序。
Initialize the Loader (初始化Loader)
记得通过另外一个进程从Contact Provider获取数据。可以使用在LoaderManager类和LoaderManager.LoaderCallbacks定义的Loader framework完成获取数据。
当你准备获取对应的行时,调用initLoader(),将一个整型标识符传入这个函数,这个标示符将传入到LoaderManager.LoaderCallbacks函数中。这个标示符可以让你在一个app中使用多个不同的loader。
下面代码展示如何初始化loader framework
public class DetailsFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor> {
...
// Defines a constant that identifies the loader
DETAILS_QUERY_ID = 0;
...
/*
* Invoked when the parent Activity is instantiated
* and the Fragment's UI is ready. Put final initialization
* steps here.
*/
@Override
onActivityCreated(Bundle savedInstanceState) {
...
// Initializes the loader framework
getLoaderManager().initLoader(DETAILS_QUERY_ID, null, this);
Implement onCreateLoader() (实现onCreateLoader()函数)
当你调用initLoader后,系统会调用onCreateLoader()函数。在这个函数中返回一个CursorLoader。使用Data.CONTENT_URI作为content URI。 @Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
// Choose the proper action
switch (loaderId) {
case DETAILS_QUERY_ID:
// Assigns the selection parameter
mSelectionArgs[0] = mLookupKey;
// Starts the query
CursorLoader mLoader =
new CursorLoader(
getActivity(),
Data.CONTENT_URI,
PROJECTION,
SELECTION,
mSelectionArgs,
SORT_ORDER
);
...
}
Implement onLoadFinished() and onLoaderReset() (实现onLoadFinished()和onLoaderReset()函数)
当Contracts Provider返回查找的结果时,loader framework会调用onLoadFinished()函数:
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
switch (loader.getId()) {
case DETAILS_QUERY_ID:
/*
* Process the resulting Cursor here.
*/
}
break;
...
}
}
当loader framework发现返回的Cursor变化是,会调用onLoaderReset()函数。在这个函数中,记得将Cursor对应的引用设为null,不然回收器将不会回收这个老的cursor。
@Override
public void onLoaderReset(Loader<Cursor> loader) {
switch (loader.getId()) {
case DETAILS_QUERY_ID:
/*
* If you have current references to the Cursor,
* remove them here.
*/
}
break;
}
Retrieve Specific Details for a Contact (获取联系人的特定信息)
可以通过下面步骤获取联系人信息的特定项。
Projection (投射)
将你的投射数组改为你想获得的数据类型所在的列。使用定义在ContactsContract.CommonDataKinds子类中定义的数据类型名。
Selection (选择)
修改选择文本为你想要查找的数据类型对应的MIMETYPE
Sort order (排列顺序)
不需要按组将返回的Cursor排序
下面展示这些变化
Define a projection (定义一个投射数组)
使用ContactsContract.CommonDataKinds子类定义的你想要的数据类型的列名。如果你想将查找结果通过Cursor与ListView绑定,记得添加_ID列。下面例子展示获取email对应的projection:
private static final String[] PROJECTION =
{
Email._ID,
Email.ADDRESS,
Email.TYPE,
Email.LABEL
};
注意这里使用的是类ContactsContract.CommonDataKinds定义的列名,而不是ContactsContract.Data定义的。对于列名,你也可以使用定义在ContactsContract.CommonDataKinds子类定义的。
Define selection criteria (定义选择规则)
定义查找的文本表达式,以便获取指定的LOOKUP_KEY和Data.MIMETYPE联系人所在的行。将MIMETYPE放在单引号内以区分边界,不然provider将会把这个常量解析成变量而不是一个字符串值。
/*
* Defines the selection clause. Search for a lookup key
* and the Email MIME type
*/
private static final String SELECTION =
Data.LOOKUP_KEY + " = ?" +
" AND " +
Data.MIMETYPE + " = " +
"'" + Email.CONTENT_ITEM_TYPE + "'";
// Defines the array to hold the search criteria
private String[] mSelectionArgs = { "" };
Define a sort order (定义排列顺序)
由于你获取的是指定的数据类型,因此不用排序,但是当你查找的数据中含有subtype,需要排序。比如:
private static final String SORT_ORDER = Email.TYPE + " ASC ";