通讯录数据的存取(二)—— 获取通讯录的具体信息

来源:互联网 发布:linux目录结构 编辑:程序博客网 时间:2024/06/08 12:16

获取通讯录的具体信息

这一节展示如何获取联系人的具体信息,如email地址,电话号码等。首先假设你已经阅读过通讯录数据的存取(一)——获取通讯录列表, 获取了通讯录列表。
分两节:
- 获取联系人的所有信息
- 获取联系人的某类型信息

获取联系人的所有信息

实现方案是搜索ContactsContract.Data表中包含联系人的LOOKUP_KEY的所有行。Contacts Provider会对ContactsContract.Data表和ContactsContract.Contacts表做一个连接,因此LOOKUP_KEY这一列也可以在ContactsContract.Data表中找到。

申请权限:

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

设置一个规划(projection)

根据数据类型的不同,Data表中的一行可能只使用某些列。数据类型不同,使用的列也不同。为保证获取所有可能的数据类型,需要将所有的列名都添加到规划中。如果需要将结果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            };

定义选择标准

定义一个选择预计常量,一个包含搜索参数的数列,一个保存待搜索值的变量。使用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注入的可能性。
使用变量来表示待搜索的内容,即SQL中替换“?”的内容。

定义排序方式

定义搜索结果的排序方式。如想让每种类型的数据在一起,可以使用Data.MIME来排序。这样结果中所有的email类型数据的行在一起,所有的电话类型数据的行在一起。如下:

  /*     * Defines a string that specifies a sort order of MIME type     */    private static final String SORT_ORDER = Data.MIMETYPE;

初始化CursorLoader

获取Contacts Provider数据的过程必须在后台线程中进行。使用Loader框架可以实现后台获取。它包含LoaderManager类和LoaderManager.LoaderCallbacks接口.
当准备获取数据时,先通过调用initLoader()初始化loader框架.需要传输一个整型参数给该方法,该参数会传递给LoaderManager.LoaderCallbacks方法。在同一个应用程序包含多个loader的情况下,可以使用该参数区分不同的loader。
代码如下:

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);

实现onCreateLoader()

该方法会在我们调用initLoader()后立即被loader框架调用。
因为搜索的是ContactsContract.Data表,使用DATA.CONTENT_URI作为内容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                    );            ...    }

其中DETAILS_QUERY_ID正是上一节中传递的整型参数。

实现onLoadFinished()和onLoadReset()

Loader框架在Contacts Provider返回搜索结果时调用onLoadFinished().代码如下:

    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {        switch (loader.getId()) {            case DETAILS_QUERY_ID:                    /*                     * Process the resulting Cursor here.                     */                }                break;            ...        }    }

onLoaderReset()方法会在loader框架发现Cursor结果的数据发生改变时被调用。在该方法中,需要清除所有对上述Cursor的引用,否则loader框架不会回收该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;    }

至此,已经讲完了搜索通信人全部具体信息的所有关键点。

获取联系人的某类型信息

获取联系人的某类型信息,如所有的email,按照上一节的步骤执行,只需修改一下几项:
规划(Projection): 修改只获取某类型的列。 使用ContactsContract.CommonDataKinds的与类型匹配的子类的列名常量。
选择(Selection):添加MIMETYPE值的搜索语句。
排序(Sort order):无需根据Data.MIMETYPE对搜索结果cursor进行排序。

定义一个规划(projection)

使用ContactsContract.CommonDataKinds的与类型匹配的子类的列名常量。如:

  private static final String[] PROJECTION =            {                Email._ID,                Email.ADDRESS,                Email.TYPE,                Email.LABEL            };

上述关于获取Email数据的规划,使用了ContactsContract.CommonDataKinds.Email类定义的列名,而没有使用ContactsContract.Data类的列名,前者可读性更强。

定义选择标准

定义一个使用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 = { "" };

定义排序方式

忽略根据Data.MIMETYPE对搜索结果cursor进行排序。如果待搜索数据的类型包含子类的话,可以使用该子类来排序。例如以Email.TYPE排序:

    private static final String SORT_ORDER = Email.TYPE + " ASC ";
0 0
原创粉丝点击