2.0联系人增、删、改、查

梦工厂 2011-09-22

推荐安卓开发神器(里面有各种UI特效和android代码库实例)

本章和大家分享的是手机通讯录方面的经验,需求背景:对手机通讯录进行增、删、改、查,或者有时候App需要与手机 contacts进行交互或共享contacts。

我们都知道android系统没有完全将contacts向developer开放,开发人员只能通过android提供的有限的Api对contacts进行操作,我们只能通过ContentProvider对contacts的数据进行增、删、改、查等操作,并不能改变到其表结构。

首先,我们来看下如何通过ContentProvider查找contacts,以下我以查找其姓、名、公司、家庭电话、工作电话、移动电话、传真、邮箱、城市、省份、国家、出生年月为例:

/**
	 * 取得family_name和given_name
	 */
	Cursor nameCur=cr.query(ContactsContract.Data.CONTENT_URI,
			new String[] {Data.CONTACT_ID, StructuredName.DISPLAY_NAME, StructuredName.FAMILY_NAME, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME},
			 ContactsContract.Data.CONTACT_ID + "=?" + " AND "
          + ContactsContract.Data.MIMETYPE + "='" +  ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'",
			new String[]{android_id}, null);
	if(nameCur.moveToFirst()){
		firstName=nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
		lastName=nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
	}
	nameCur.close();
 
	Cursor companyCur=cr.query(ContactsContract.Data.CONTENT_URI,
			new String[] {CommonDataKinds.Organization.COMPANY},
			 ContactsContract.Data.CONTACT_ID + "=?" + " AND "
          + ContactsContract.Data.MIMETYPE + "='" +  ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE + "'",
			new String[]{android_id}, null);
 
	if(companyCur.moveToFirst()){
			company=companyCur.getString(companyCur.getColumnIndex(CommonDataKinds.Organization.COMPANY));
		}
	companyCur.close();
 
	// 根据contact_ID取得HomePhone号码
	Cursor homePhoneCur = cr.query(ContactsContract.Data.CONTENT_URI,
			new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER},
        ContactsContract.Data.CONTACT_ID + "=?" + " AND "
          + ContactsContract.Data.MIMETYPE + "=? "+" AND "
          +ContactsContract.CommonDataKinds.Phone.TYPE + "=?",
        new String[]{android_id,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_HOME)}, null);
	if(homePhoneCur.moveToFirst()){
		homePhone=homePhoneCur.getString(homePhoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
	}
	homePhoneCur.close();
 
	// 根据contact_ID取得WorkPhone号码
	Cursor workPhoneCur = cr.query(ContactsContract.Data.CONTENT_URI,
			new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER},
        ContactsContract.Data.CONTACT_ID + "=?" + " AND "
          + ContactsContract.Data.MIMETYPE + "=? "+" AND "
          +ContactsContract.CommonDataKinds.Phone.TYPE + "=?",
        new String[]{android_id,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_WORK)}, null);
	if(workPhoneCur.moveToFirst()){
		workPhone=workPhoneCur.getString(workPhoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
	}
	workPhoneCur.close();
 
	// 根据contact_ID取得MobilePhone号码
	Cursor mobilePhoneCur = cr.query(ContactsContract.Data.CONTENT_URI,
			new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER},
        ContactsContract.Data.CONTACT_ID + "=?" + " AND "
          + ContactsContract.Data.MIMETYPE + "=? "+" AND "
          +ContactsContract.CommonDataKinds.Phone.TYPE + "=?",
        new String[]{android_id,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)}, null);
	if(mobilePhoneCur.moveToFirst()){
		mobilePhone=mobilePhoneCur.getString(mobilePhoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
	}
	mobilePhoneCur.close();
 
	// 根据contact_ID取得MobilePhone号码
	Cursor faxPhoneCur = cr.query(ContactsContract.Data.CONTENT_URI,
			new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER},
        ContactsContract.Data.CONTACT_ID + "=?" + " AND "
          + ContactsContract.Data.MIMETYPE + "=? "+" AND "
          +ContactsContract.CommonDataKinds.Phone.TYPE + "=?",
        new String[]{android_id,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME)}, null);
	if(faxPhoneCur.moveToFirst()){
		faxPhone=faxPhoneCur.getString(faxPhoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
	}
	faxPhoneCur.close();
 
	// 根据contact_ID取得MobilePhone号码
	Cursor emailCur = cr.query(ContactsContract.Data.CONTENT_URI,
			new String[] {ContactsContract.CommonDataKinds.Email.DATA},
        ContactsContract.Data.CONTACT_ID + "=?" + " AND "
          + ContactsContract.Data.MIMETYPE + "=? "+" AND "
          +ContactsContract.CommonDataKinds.Phone.TYPE + "=?",
        new String[]{android_id,ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Email.TYPE_WORK)}, null);
	if(emailCur.moveToFirst()){
		email=emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
	}
	emailCur.close();
 
	// 根据contact_ID取得MobilePhone号码
	Cursor addressCur = cr.query(ContactsContract.Data.CONTENT_URI,
			new String[] {ContactsContract.CommonDataKinds.StructuredPostal.CITY,ContactsContract.CommonDataKinds.StructuredPostal.REGION,
			ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY},
        ContactsContract.Data.CONTACT_ID + "=?" + " AND "
        + ContactsContract.Data.MIMETYPE + "=? ",
        new String[]{android_id,ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE}, null);
	if(addressCur.moveToFirst()){
		city=addressCur.getString(addressCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
		state=addressCur.getString(addressCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION));
		country=addressCur.getString(addressCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
	}
	addressCur.close();
 
	// 根据contact_ID取得MobilePhone号码
	Cursor birthdayCur = cr.query(ContactsContract.Data.CONTENT_URI,
			new String[] {ContactsContract.CommonDataKinds.Event.DATA},
        ContactsContract.Data.CONTACT_ID + "=?" + " AND "
          + ContactsContract.Data.MIMETYPE + "=? "+" AND "
          + ContactsContract.CommonDataKinds.Event.TYPE + "=? ",
        new String[]{android_id,ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY)}, null);
	if(birthdayCur.moveToFirst()){
		birthday=birthdayCur.getString(birthdayCur.getColumnIndex(ContactsContract.CommonDataKinds.Event.DATA));
	}
	birthdayCur.close();

以上只是查找了contacts的部分字段,同鞋们可以自行拓展,比如说查找其IM,Organization,Nickname,WebSite等等.

得到contacts联系人之后,我们可以对其做相应的修改,修改完成后,我们要将数据更新到android contacts数据库中,以下就是更新的范例:

ArrayList ops =
	          new ArrayList();
		// 更新family_name和given_name
	 ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
	          .withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND "
	        		  + ContactsContract.Data.MIMETYPE + "=?",
	        		  new String[]{android_id,ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE})
                        .withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, firstN)
                        .withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, lastN)
                        .build());
	 // 更新comany
	 ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
	          .withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND "
	        		  + ContactsContract.Data.MIMETYPE + "=?"+ " AND "
	        		  + ContactsContract.CommonDataKinds.Organization.TYPE + "=?",
	        		  new String[]{android_id,ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Organization.TYPE_WORK)})
                       .withValue(ContactsContract.CommonDataKinds.Organization.COMPANY, com)
                       .build());
	 // 更新homePhone
	 ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
	          .withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND "
	        		  + ContactsContract.Data.MIMETYPE + "=?"+ " AND "
	        		  + ContactsContract.CommonDataKinds.Organization.TYPE + "=?",
	        		  new String[]{android_id,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_HOME)})
                      .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, hp)
                      .build());
	 // 更新workPhone
	 ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
	          .withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND "
	        		  + ContactsContract.Data.MIMETYPE + "=?"+ " AND "
	        		  + ContactsContract.CommonDataKinds.Organization.TYPE + "=?",
	        		  new String[]{android_id,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_WORK)})
                     .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER,wp)
                     .build());
	// 更新mobilePhone
	 ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
	          .withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND "
	        		  + ContactsContract.Data.MIMETYPE + "=?"+ " AND "
	        		  + ContactsContract.CommonDataKinds.Organization.TYPE + "=?",
	        		  new String[]{android_id,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)})
                    .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER,mp)
                    .build());
	// 更新faxPhone
	 ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
	          .withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND "
	        		  + ContactsContract.Data.MIMETYPE + "=?"+ " AND "
	        		  + ContactsContract.CommonDataKinds.Organization.TYPE + "=?",
	        		  new String[]{android_id,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME)})
                    .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER,fp)
                    .build());
	// 更新email
	 ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
	          .withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND "
	        		  + ContactsContract.Data.MIMETYPE + "=?"+ " AND "
	        		  + ContactsContract.CommonDataKinds.Email.TYPE + "=?",
	        		  new String[]{android_id,ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Email.TYPE_WORK)})
                   .withValue(ContactsContract.CommonDataKinds.Email.DATA,em)
                   .build());
	// 更新city,state,country
	 ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
	          .withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND "
	        		  + ContactsContract.Data.MIMETYPE + "=?"+ " AND "
	        		  + ContactsContract.CommonDataKinds.StructuredPostal.TYPE + "=?",
	        		  new String[]{android_id,ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.StructuredPostal.TYPE_HOME)})
                  .withValue(ContactsContract.CommonDataKinds.StructuredPostal.CITY, city)
                  .withValue(ContactsContract.CommonDataKinds.StructuredPostal.REGION, state)
                  .withValue(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY,cou)
                  .build());
	// 更新birthday
	 ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
	          .withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND "
	        		  + ContactsContract.Data.MIMETYPE + "=?"+ " AND "
	        		  + ContactsContract.CommonDataKinds.Event.TYPE + "=?",
	        		  new String[]{android_id,ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE,String.valueOf(ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY)})
                 .withValue(ContactsContract.CommonDataKinds.Event.DATA, bir)
                 .build());
	 try
     {
         ContentProviderResult[] res = context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
	//  Log.i("contact", "android_id="+android_id+",firstName="+firstName+",lastName="+lastName);
	//  appState.db.insertContactToTag(tagId,String.valueOf(contactId));
     }
     catch (RemoteException e)
     {
         // error
     }catch (OperationApplicationException e)
     {
         // error
     }

同样以上更新也仅是对contact的部分字段进行了更新,我相信聪明的你,仔细阅读,细细推敲一番,定能找到其中的规律,从而对犹如IM,Nickname,Event,Organization等字段进行更新。

以上只是对已经存在的contacts进行操作,那么我们一开始该如何向里面插入一条数据呢,以下代码是实现向数据库中插入一条数据的操作。

ArrayList ops = new ArrayList();
		int rawContactInsertIndex = ops.size();
 
        ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
                .build());
 
      //------------------------------------------------------ Names
        if(firstN != null && lastN!=null )
        {
            ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                    .withValue(ContactsContract.Data.MIMETYPE,
                            ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, firstN+lastN)
                    .withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, firstN)
                    .withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, lastN)
                    .build());
        }  
 
      //------------------------------------------------------ Organization
        if(com!=null)
        {
            ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                    .withValue(ContactsContract.Data.MIMETYPE,
                            ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.Organization.COMPANY, com)
                    .withValue(ContactsContract.CommonDataKinds.Organization.TYPE, ContactsContract.CommonDataKinds.Organization.TYPE_WORK)
                    .build());
        }
 
      //------------------------------------------------------ Home Numbers
        if(hp!= null)
        {
            ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                    .withValue(ContactsContract.Data.MIMETYPE,
                            ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, hp)
                    .withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
                            ContactsContract.CommonDataKinds.Phone.TYPE_HOME)
                    .build());
        }
      //------------------------------------------------------ Work Numbers
        if(wp != null)
        {
            ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                    .withValue(ContactsContract.Data.MIMETYPE,
                            ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, wp)
                    .withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
                            ContactsContract.CommonDataKinds.Phone.TYPE_WORK)
                    .build());
        }
      //------------------------------------------------------ Mobile Number
        if(mp != null)
        {
            ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                    .withValue(ContactsContract.Data.MIMETYPE,
                            ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, mp)
                    .withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
                            ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
                    .build());
        }
      //------------------------------------------------------ Fax Number
        if(fp != null)
        {
            ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                    .withValue(ContactsContract.Data.MIMETYPE,
                            ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, fp)
                    .withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
                            ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME)
                    .build());
        }
 
      //------------------------------------------------------ Email
        if(em != null)
        {
             ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                        .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                        .withValue(ContactsContract.Data.MIMETYPE,
                                ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
                        .withValue(ContactsContract.CommonDataKinds.Email.DATA, em)
                        .withValue(ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.TYPE_WORK)
                        .build());
        }
      //------------------------------------------------------ City,state,country
        if(city != null)
        {
             ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                        .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                        .withValue(ContactsContract.Data.MIMETYPE,
                                ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)
                        .withValue(ContactsContract.CommonDataKinds.StructuredPostal.CITY, city)
                        .withValue(ContactsContract.CommonDataKinds.StructuredPostal.REGION, state)
                        .withValue(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY,cou)
                        .withValue(ContactsContract.CommonDataKinds.StructuredPostal.TYPE,
                        		ContactsContract.CommonDataKinds.StructuredPostal.TYPE_HOME)
                        .build());
        }
 
      //------------------------------------------------------ Birthday
        if(bir != null)
        {
             ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                        .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                        .withValue(ContactsContract.Data.MIMETYPE,
                                ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE)
                        .withValue(ContactsContract.CommonDataKinds.Event.DATA, bir)
                        .withValue(ContactsContract.CommonDataKinds.Event.TYPE,
                        		ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY)
                        .build());
        }
        try
        {
            ContentProviderResult[] res = context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
 
            return res;
        }
        catch (RemoteException e)
        {
            // error
        }catch (OperationApplicationException e)
        {
            // error
        }

实现以上代码便可将一条数据插入到contacts数据库中,同样,你也可以插入其他的字段,而且你也可以细细研究下ContentProviderResult[],看看进行这些操作后,其返回的结果都是什么。

以上实现了对android contacts 增、删、改、查中的三种,下面的代码就是实现删的,删除一个contacts相对来说比较简单些。

String where = ContactsContract.Data._ID + " = ? ";
    	String[] params = new String[] {android_id};
 
        ArrayList ops = new ArrayList();
        ops.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI)
    	        .withSelection(where, params)
    	        .build());
        try {
		cr.applyBatch(ContactsContract.AUTHORITY, ops);
	} catch (RemoteException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (OperationApplicationException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

删除一个contacts有很多的选择,你可以只删除电话这一块,也可以删除联系人信息这一块,而且你不仅可以将id做作为条件进行删除,你也可以将联系电话做为条件进行删除,你也还可以以用户名做为条件进行删除。

以上代码便可以实现对android contacts的增、删、改、查等操作。最后不要忘了赋予APP 对contacts读写的权限:

相关推荐