在Android 2.2中插入联系人

27
我正在尝试插入新的 RawContact 联系人,但是当我通过 Contacts 或电话簿查看联系人时,添加的 RawContact 不会显示出来。我理解如果我们创建一个 RawContact 并且没有与之关联的联系人,则联系人将自动插入。我得到了一个有效的 rawContactId 值,也没有抛出任何异常,所以我认为插入成功了。我是否做错了什么或者我漏掉了什么?我正在使用开发者网站上的示例代码,只是在这里粘贴:
 ContentValues values = new ContentValues();
 values.put(RawContacts.ACCOUNT_TYPE, accountType); 
 values.put(RawContacts.ACCOUNT_NAME, accountName);
 Uri rawContactUri = getContentResolver().insert(RawContacts.CONTENT_URI, values); 
 long rawContactId = ContentUris.parseId(rawContactUri); 

 values.clear(); 
 values.put(Data.RAW_CONTACT_ID, rawContactId); 
 values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); 
 values.put(StructuredName.DISPLAY_NAME, "Mike Sullivan"); 
 getContentResolver().insert(Data.CONTENT_URI, values); 
3个回答

37

我以为这个问题早就被遗忘了,但既然有人点赞了它,我就认为还有其他人也遇到了和我一样的问题。经过一番努力,我终于找出了问题并成功插入了联系人。希望这可以帮到你们,以下是示例代码:

ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
int rawContactInsertIndex = ops.size();

ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
   .withValue(RawContacts.ACCOUNT_TYPE, null)
   .withValue(RawContacts.ACCOUNT_NAME,null )
   .build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
   .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
   .withValue(Data.MIMETYPE,Phone.CONTENT_ITEM_TYPE)
   .withValue(Phone.NUMBER, "9X-XXXXXXXXX")
   .build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
   .withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex)
   .withValue(Data.MIMETYPE,StructuredName.CONTENT_ITEM_TYPE)
   .withValue(StructuredName.DISPLAY_NAME, "Mike Sullivan")
   .build());  
ContentProviderResult[] res = getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);

这个解决方案直接添加联系人。有没有一种方法可以启动Android的“添加联系人”活动,并填充一些预设数据(包括StructuredName)?如果有,请在此回答:https://dev59.com/ElvUa4cB1Zd3GeqPvJ2g - Dino
如果我在三星手机上使用“null”作为账户名称和类型,在执行applyBatch时会出现错误。有任何更新吗? - Simon MacDonald
它运行良好。请告诉我如何在插入联系人后获取联系人ID。 - AndroidRaji
为什么要添加联系人两次? - Tofeeq Ahmad
应该导入哪些数据?ContactsContract.Data、ContactsContract.Contacts.Data还是ContactsContract.RawContacts.Data? - Sarthak Majithia
如果getContentResolver无法工作,因为你在一个片段中,请首先调用getActivity()。如果ContentProviderResult无法工作,请尝试以下代码:try { ContentProviderResult[] res = getContentResolver().applyBatch( ContactsContract.AUTHORITY, ops); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (OperationApplicationException e) { // TODO Auto-generated catch block e.printStackTrace(); } - NVA

7

有客户向我报告,在某些HTC设备上,上面Als提供的解决方案并不能起作用。因此,在经过几天的挣扎后,我想出了以下解决方案:

String name = "First Family";
String phone = "0123456789";
ContentValues values = new ContentValues();
values.put(Data.DISPLAY_NAME, name);
Uri rawContactUri = c.getContentResolver().insert(RawContacts.CONTENT_URI, values);
long rawContactId = ContentUris.parseId(rawContactUri);
long contactId = Util.getContactId(c, rawContactId);
System.out.println("rawContactId = " + rawContactId);
System.out.println("contactId = " + contactId);

values.clear();
values.put(Phone.NUMBER, phone);
values.put(Phone.TYPE, Phone.TYPE_OTHER);
values.put(Phone.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
values.put(Data.RAW_CONTACT_ID, rawContactId);
c.getContentResolver().insert(Data.CONTENT_URI, values);

values.clear();
values.put(Data.MIMETYPE, Data.CONTENT_TYPE);
values.put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);
values.put(Data.RAW_CONTACT_ID, rawContactId);
c.getContentResolver().insert(Data.CONTENT_URI, values);

values.clear();
values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);
values.put(Data.RAW_CONTACT_ID, rawContactId);
c.getContentResolver().insert(Data.CONTENT_URI, values);



public static long getContactId(Context context, long rawContactId) {
    Cursor cur = null;
    try {
        cur = context.getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI, new String[] { ContactsContract.RawContacts.CONTACT_ID }, ContactsContract.RawContacts._ID + "=" + rawContactId, null, null);
        if (cur.moveToFirst()) {
            return cur.getLong(cur.getColumnIndex(ContactsContract.RawContacts.CONTACT_ID));
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (cur != null) {
            cur.close();
        }
    }
    return -1l;
}

public static long getContactId(Context context, long rawContactId) { Cursor cur = null; try { cur = context.getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI, new String[] { ContactsContract.RawContacts.CONTACT_ID }, ContactsContract.RawContacts._ID + "=" + rawContactId, null, null); if (cur.moveToFirst()) { return cur.getLong(cur.getColumnIndex(ContactsContract.RawContacts.CONTACT_ID)); } } catch (Exception e) { e.printStackTrace(); } finally { if (cur != null) { cur.close(); } } return -1l; } - Milan
@anqe1ki11er:我在我写的代码中没有看到任何特定于设备的内容。它完全是基于原生的Android框架,所以我不确定为什么它会在某些特定的设备上失败。这个解决方案应该可以在模拟器上运行,并且适用于所有支持和使用Android原生框架的设备。我猜想HTC修改了联系人的框架。 - Alok Save
1
@Als:是的,你的代码在模拟器和几乎所有设备上都可以完美运行。所以我同意你的观点,这很可能是HTC修改了联系人框架的问题。 - Milan
@anqe1ki11er:我不理解第三段中的{values.put(Data.MIMETYPE,Data.CONTENT_TYPE)}。没有这样的MIMETYPE。(我在运行HTC Android 2.2的HTC Desire上进行了检查)。谢谢。 - OferR
为什么在Util.getContactId(c, rawContactId)中显示错误?c是什么? - AndroidRaji
显示剩余4条评论

1
为了创建一个可见的联系人,它需要属于一个可见的群组。在您的计算机上查看Gmail联系人以查看群组和可见性。
要在设备上找到可见的群组,请执行以下操作:
    Long myContactsGroupId = null;
    sqlWhere = ContactsContract.Groups.ACCOUNT_TYPE + " = 'com.google'  AND  " + ContactsContract.Groups.GROUP_VISIBLE + " = 1";
    Cursor cursor = getContentResolver().query(ContactsContract.Groups.CONTENT_URI, new String[] {"_id"}, sqlWhere, null, "_id");
    if (cursor.moveToFirst()) {
        myContactsGroupId = cursor.getLong(0);
    }

将该组添加到原始联系人:

        cv.clear();
        cv.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE);
        cv.put(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID, myContactsGroupId);
        cv.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
        getContentResolver().insert(ContactsContract.Data.CONTENT_URI, cv);

或者是 ops 版本:

         ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE,
                        ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID, myContactsGroupId)
                .build());

@anqe1ki11er:

我不理解你回答中第三段所说的内容:

values.put(Data.MIMETYPE, Data.CONTENT_TYPE) ...

并不存在这样的 MIMETYPE。(我在运行 HTC Android 2.2 的 HTC Desire 上进行了确认。)

谢谢。


谢谢,ops版本救了我的一天!!顺便说一句,它可以在Android 4.2.3上运行。 - Dr.Luiji

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接