如何查询属于一个帐户的所有联系人? [英] How to query all contacts that belong to an account?

查看:65
本文介绍了如何查询属于一个帐户的所有联系人?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通讯录上的联系人可以具有附加的帐户数据. 每个应用程序可以拥有一个帐户,然后为联系人添加自己的信息.

Contacts on the address book can have an account data that's attached to them. Each app can have an account, and then add its own information for the contact.

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

Apps such as Telegram, WhatsApp, Viber,... - all create an account that adds information and/or actions to contacts.

这是一个同时具有WhatsApp和Viber帐户的联系人的示例:

Here's an example of a contact that has both WhatsApp and Viber accounts for it:

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

I'm trying to figure out how to fetch all contacts that have a specified account.

由于WhatsApp是我所知道的最受欢迎的软件,因此我的测试重点是它.

Since WhatsApp is the most popular that I know of, my tests focus on it.

我的问题是,一些用户声称我所做的几乎没有返回联系人,而有些用户则声称甚至没有显示一个联系人.它似乎通常可以正常工作,在我看来,它总是可以工作,但是代码上可能有些不好.

My problem is that some users claim what I did barely returns contacts, and some claim it doesn't show even a single one. It seems to usually work, and in my case it always worked, but something is probably not good on the code.

我必须编写下一个代码,该代码对我来说似乎可行,并获取所有WhatsApp联系人的电话到联系人信息地图.

I got to make the next code, which to me seems to work, getting a map of phone-to-contact-info, of all WhatsApp contacts.

该想法是获取WhatsApp联系人的所有可能信息以及所有基本联系人数据,然后合并与相同查找键匹配的那些信息.

The idea is to get all possible information of WhatsApp contacts, vs all basic contacts data, and merge those that match the same lookup-key.

我尝试使用更好的加入查询,但失败了.也许也有可能,而且可能会更有效.

I tried to use a better query of joining, but I failed. Maybe it is possible too, and might be more efficient.

代码如下:

/**
 * 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;
}

问题

正如我所写,上面的代码通常只能工作.

The question

As I wrote, the above code only usually works.

为什么通常只能正常工作?缺少什么来解决它?

How come it only usually works? What's missing to fix it?

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

Should I use Contacts.getLookupUri instead of lookup key? If so, how should I change the code above to use it instead?

我尝试使用URI代替查找键,但随后在常规联系人中找不到任何一个.

I tried to use a URI instead of a lookup-key, but then it didn't find any of them inside the normal contacts.

推荐答案

我看到的主要问题可以解释,为什么用户看不到代码的结果,就是假设所有联系人都存储在Google帐户.

The main issue I see that can explain why users won't see results from your code, is that you're assuming all the contacts are stored on a Google account.

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

While this is the default behavior in some devices, it's not the default on all devices, also, users can freely change their contacts storage to any other location (yahoo contacts, MS exchange, phone-only (unsynced), etc.)

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

Having that said, if your only requirement is to

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

fetch all contacts that have a specified account.

我认为这是一个比您的2个查询更好的选择(其中2个查询运行在所有联系人上,而不仅仅是需要的联系人):

I think that's a much better alternative then your 2 queries (one of which runs over all contacts, not just the required ones):

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

这篇关于如何查询属于一个帐户的所有联系人?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆