如何查询属于某个帐户的所有联系人?

and*_*per 5 android android-contacts

背景

地址簿上的联系人可以拥有附加到他们的帐户数据.每个应用都可以拥有一个帐户,然后为该联系人添加自己的信息.

诸如Telegram,WhatsApp,Viber等应用程序 - 都创建了一个向联系人添加信息和/或操作的帐户.

以下是一个包​​含WhatsApp和Viber帐号的联系人示例:

在此输入图像描述

问题

我正在试图弄清楚如何获取具有指定帐户的所有联系人.

由于WhatsApp是我所知道的最受欢迎的,我的测试专注于它.

我的问题是,有些用户声称我几乎没有回复联系人,有些人声称它甚至没有显示任何一个.它似乎通常工作,在我的情况下,它总是有效,但在代码上可能不是很好.

我试过的

我必须制作下一个代码,这对我来说似乎有用,可以获得所有WhatsApp联系人的电话到联系信息的地图.

我们的想法是获取WhatsApp联系人与所有基本联系人数据的所有可能信息,并合并那些匹配相同查找密钥的信息.

我试图使用更好的加入查询,但我失败了.也许它也有可能,并且可能更有效率.

这是代码:

/**
 * returns a map of lookup-key to contact-info, of all WhatsApp contacts
 */
@NonNull
public HashMap<String, ContactInfo> getAllWhatsAppPhones(Context context) {
    ContentResolver cr = context.getContentResolver();
    final HashMap<String, ContactInfo> phoneToContactInfoMap = new HashMap<>();
    final HashMap<String, String> whatsAppLookupKeyToPhoneMap = new HashMap<>();
    final String phoneMimeType = Phone.CONTENT_ITEM_TYPE;
    final Cursor whatsAppCursor;
    whatsAppCursor = cr.query(Data.CONTENT_URI,
            new String[]{Phone.NUMBER, Phone.LOOKUP_KEY},
            Phone.MIMETYPE + " = ?", new String[]{WhatsAppStuff.WHATS_APP_MIME_TYPE}, null);
    if (whatsAppCursor == null)
        return phoneToContactInfoMap;
    Cursor contactCursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            //null,
            new String[]{
                    Contacts.LOOKUP_KEY, Contacts._ID, Contacts.PHOTO_THUMBNAIL_URI,
                    ContactsContract.Contacts.DISPLAY_NAME,                        //        ContactsContract.CommonDataKinds.Phone.NUMBER,
            },
            "(" + Phone.MIMETYPE + " IS NULL OR " + Phone.MIMETYPE + " = '" + phoneMimeType + "') AND ("
                    + ContactsContract.RawContacts.ACCOUNT_TYPE + " = 'com.google' OR " + ContactsContract.RawContacts.ACCOUNT_TYPE + " IS NULL)",
            null, null);
    if (contactCursor == null) {
        whatsAppCursor.close();
        return phoneToContactInfoMap;
    }
    int progress = 0;
    final int phoneNumberIdx = whatsAppCursor.getColumnIndex(Phone.NUMBER);
    final int lookupKeyIdx = whatsAppCursor.getColumnIndex(Phone.LOOKUP_KEY);
    while (whatsAppCursor.moveToNext()) {
        final String phoneNumberValue = whatsAppCursor.getString(phoneNumberIdx);
        final int endIndex = phoneNumberValue.indexOf("@");
        if (endIndex < 0)
            continue;
        String lookupKey = whatsAppCursor.getString(lookupKeyIdx);
        final String phone = phoneNumberValue.substring(0, endIndex);
        if (!phone.isEmpty() && StringUtil.isAllDigits(phone)) {
            //Log.d("AppLog", "whatsApp phone:" + phone + " " + lookupKey);
            whatsAppLookupKeyToPhoneMap.put(lookupKey, phone);
        }
        if (markedToCancel != null && markedToCancel.get()) {
            whatsAppCursor.close();
            contactCursor.close();
            return phoneToContactInfoMap;
        }
        if (progressListener != null)
            progressListener.onProgressUpdate(progress++, maxProgress);
    }
    whatsAppCursor.close();
    if (whatsAppLookupKeyToPhoneMap.isEmpty())
        return phoneToContactInfoMap;
    //Log.d("AppLog", "getting info about whatsapp contacts");
    final int idColIdx = contactCursor.getColumnIndex(Contacts._ID);
    final int displayNameColIdx = contactCursor.getColumnIndex(Contacts.DISPLAY_NAME);
    final int lookupKeyColIdx = contactCursor.getColumnIndex(Contacts.LOOKUP_KEY);
    final int photoColIdx = contactCursor.getColumnIndex(Contacts.PHOTO_THUMBNAIL_URI);

    while (contactCursor.moveToNext()) {
        String lookupKey = contactCursor.getString(lookupKeyColIdx);
        String phoneNumber = whatsAppLookupKeyToPhoneMap.get(lookupKey);
        if (phoneNumber == null)
            continue;
        ContactInfo contactInfo = new ContactInfo();
        contactInfo.lookupKey = lookupKey;
        contactInfo.displayName = contactCursor.getString(displayNameColIdx);
        contactInfo.photoThumbUriStr = contactCursor.getString(photoColIdx);
        contactInfo.whatsAppPhoneNumber = phoneNumber;
        contactInfo.contactId = contactCursor.getLong(idColIdx);
        phoneToContactInfoMap.put(phoneNumber, contactInfo);
        if (markedToCancel != null && markedToCancel.get()) {
            contactCursor.close();
            return phoneToContactInfoMap;
        }
        if (progressListener != null)
            progressListener.onProgressUpdate(progress++, maxProgress);
    }
    contactCursor.close();
    return phoneToContactInfoMap;
}
Run Code Online (Sandbox Code Playgroud)

这个问题

正如我所写,上述代码通常只能起作用.

为什么它通常只能起作用?修复它有什么缺点?

我应该使用Contacts.getLookupUri而不是查找键吗?如果是这样,我应该如何更改上面的代码才能使用它?

我试图使用URI而不是查找键,但后来在正常联系人中找不到任何一个.

mar*_*mor 4

我发现可以解释为什么用户看不到代码结果的主要问题是您假设所有联系人都存储在一个Google帐户中。

虽然这是某些设备上的默认行为,但并非所有设备上的默认行为,而且用户可以自由地将其联系人存储更改为任何其他位置(yahoo 联系人、MS Exchange、仅电话(未同步)等)

话虽如此,如果您唯一的要求是

获取具有指定帐户的所有联系人。

我认为这是一个比您的两个查询更好的选择(其中一个查询针对所有联系人,而不仅仅是所需的联系人):

// Uri to query contacts that have a RawContact in the desired account
final Uri.Builder builder = Contacts.CONTENT_URI.buildUpon();
builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, whatsappAccountName);
builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, whatsappAccountType);
Uri uri = builder.build();

String[] projection = new String[]{ Contacts.LOOKUP_KEY, Contacts._ID Contacts.DISPLAY_NAME }; // add more if needed

// boo-yaa!
Cursor cur = cr.query(uri, projection, null, null, null);
Run Code Online (Sandbox Code Playgroud)