Android联系人模块分析(一)


     联系人模块是Android系统中的一个重要的功能模块,目前Android市场上有大量的基于通讯录的应用,本人计划写出系列文章详细介绍联系人模块的结构和使用。作为开头,本篇文章将对ContactsProvider做个简要的介绍。

     Android系统将联系人的信息存储在sqlite数据库中,并通过ContactsProvider提供查询、更新、删除等操作。所以如果需要掌握联系人相关信息的操作,就需要掌握ContactsProvider的内容。

       在开始学习ContactsProvider的内容之前,读者需要对ContentProvider机制有较深入的理解,ContactsProvider本质上就是Android内建的一种ContentProvider。ContentProvider是Android系统用来在所有应用程序之间共享数据的一种方法。下面我就从数据访问和存储的角度来介绍如何自定义一个ContentProvider,数据存储在sqlite中:

       1、提供外部访问的接口:访问接口是数据操作的前提,用户不需要知道内部数据的存储方式,只要通过数据访问接口就可以获取Provider中的数    据信息,以下为ContentProvider.java中定义的数据访问、操作的接口:     

      public abstract Cursor query(Uri uri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder);
	 public abstract Uri insert(Uri uri, ContentValues values);
      public abstract int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs); 

    实现自定义ContentProvider,可以直接或间接的派生ContentProvider类,并override以上几种数据操作方法。

            ContactsProvider为例,在ContactsProvider2.java文件中,我们可以看到:

      public class ContactsProvider2 extends AbstractContactsProvider implements OnAccountsUpdateListener
      public abstract class AbstractContactsProvider extends ContentProvider implements SQLiteTransactionListener

     ContactsProvider派生自AbstractContactsProvider,而AbstractContactsProvider又从ContentProvider派生,从AbstractContactsProvider.java中我们就可以看到       override了一些数据操作方法。

       2、创建数据库:通过派生SQLiteOpenHelper类,创建数据库及其各个表项信息;

            在ContactsProvider中对应的即为ContactsDatabaseHelper类:  

      public class ContactsDatabaseHelper extends SQLiteOpenHelper
            为了让所有数据库访问者保持一致性,该类设计为单例类,该单例在ContactsProvider创建时创建:

      public boolean onCreate() {
          mDbHelper = new ContactsSearchDBHelper(getContext());
          return true;
      }

   通过该数据库帮助类,在访问数据库时,可以通过该帮助类获得数据库的读、写引用,如下面的insert操作:

           

      public Uri insert(Uri uri, ContentValues values) {
        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        int match = sUriMatcher.match(uri);
        long id = -1;

        synchronized (mLock) {
            db.beginTransaction();
            try {
                switch (match) {
                    /*case CONTACT_INFO:
                        id = db.insert(ContactInfo.TABLE_NAME, "", values);
                        db.setTransactionSuccessful();
                        break;*/
                    case CircleMember_DATA:
                        id = db.insert(CircleMember.TABLE_NAME, "", values);
                        db.setTransactionSuccessful();
                        break;

     3、定义数据表名、字段名,及其URI:

             在ContactsProvider中,ContactsContract类定义了该provider的权限、数据表、URI信息:

    /** The authority for the contacts provider */
    public static final String AUTHORITY = "com.android.contacts";
    /** A content:// style uri to the authority for the contacts provider */
    public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);

           Contacts数据表的定义:

      public static class Contacts implements BaseColumns, ContactsColumns,
            ContactOptionsColumns, ContactNameColumns, ContactStatusColumns {
        /**
         * This utility class cannot be instantiated
         */
        private Contacts()  {}

        /**
         * The content:// style URI for this table
         */
        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contacts");

         上述只是简单的介绍了ContactsProvider的结构,下面我们来详细介绍一下ContactsProvider中的代码:

       首先看看URI匹配表的生成逻辑:

       

    static {
        // Contacts URI matching table
        final UriMatcher matcher = sUriMatcher;
        matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS);
        matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID);
        matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA);
        matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES);
        matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions",
                AGGREGATION_SUGGESTIONS);
      从URI匹配表的生成逻辑可以看出该Provider提供了哪些查询的方法,以这一行代码为例:

      matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA);

      这个URI就是对Contact表和Data表进行关联查询,当然这个查询是需要带上contactId的,目前ContactsProvider不支持其他字段的Contact表和Data表关联查询。用户就可以根据该URI来进行如下的查询操作:

    Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
    String dataDir = ContactsContract.Contacts.Data.CONTENT_DIRECTORY;
    Uri methodUri = Uri.withAppendedPath(contactUri, dataDir);
    Cursor c = null;
    try {
                c = mContext.getContentResolver().query(methodUri,
                        null, null, null, null);
            } catch (IllegalArgumentException e) {
                if (c != null) {
                    c.close();
                }
            }

              上述查询代码就是通过contactId获得该联系人的Data表中的信息,然后根据mimetype来区分获得数据类型,如:

        String mime = c.getString(c.getColumnIndex(Data.MIMETYPE));
        if (Phone.CONTENT_ITEM_TYPE.equals(mime)) {
            就是用来判断该游标项是否为电话号码信息。

         先写到这儿,后面再整理一下,结合实际的例子来描述怎样对联系人信息进行操作。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值