每个联系人的重复电话号码android

问题描述 投票:0回答:1

在我的应用程序中,我想显示一个列表,其中包含我的联系人及其每个人的电话号码。因此,我从 ContentProvider 获取联系人,然后获取手机的所有号码,然后通过联系人 ID 进行匹配。代码如下

fun Context.retrieveAllContacts(): List<ContactData> {
    val result: MutableList<ContactData> = mutableListOf()
    contentResolver.query(
        ContactsContract.Contacts.CONTENT_URI,
        CONTACT_PROJECTION,
        null,
        null,
        ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " ASC"
    )?.use {
        if (it.moveToFirst()) {
            do {
                val contactId = it.getString(it.getColumnIndex(CONTACT_PROJECTION[0]))
                val firstName = it.getString(it.getColumnIndex(CONTACT_PROJECTION[2])) ?: ""
                val lastName = it.getString(it.getColumnIndex(CONTACT_PROJECTION[3])) ?: ""
                val initials = getInitials(firstName, lastName)
                result.add(ContactData(contactId, firstName, initials, mutableListOf(), null))
            } while (it.moveToNext())
        }
    }
    return result
}


fun Context.retrieveAllContactNumbers(): HashMap<String, ArrayList<String>> {
    val contactsNumberMap = HashMap<String, ArrayList<String>>()
    val phoneCursor: Cursor? = contentResolver.query(
        ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
        null,
        null,
        null,
        null
    )
    if (phoneCursor != null && phoneCursor.count > 0) {
        val contactIdIndex =
            phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)
        val numberIndex = phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)
        while (phoneCursor.moveToNext()) {
            val contactId = phoneCursor.getString(contactIdIndex)
            val number: String = phoneCursor.getString(numberIndex)
            // check if the map contains key or not, if not then create a new array list with number
            if (contactsNumberMap.containsKey(contactId)) {
                contactsNumberMap[contactId]?.add(number)
            } else {
                contactsNumberMap[contactId] = arrayListOf(number)
            }
        }
        // contact contains all the number of a particular contact
        phoneCursor.close()
    }
    return contactsNumberMap
}

之后我运行一个循环来进行通信

                val contactsListAsync = async { context?.retrieveAllContacts() ?: emptyList() }
                val contacts = contactsListAsync.await()
                val contactNumbersAsync = async { requireActivity().retrieveAllContactNumbers() }
                val contactNumbers = contactNumbersAsync.await()

                contacts.forEach { contactData ->
                    contactNumbers[contactData.contactId]?.let { numbers ->
                        numbers.forEach {
                            if (isValidIrisCellphoneNumber(PhoneNumberUtils.normalizeNumber(it)))
                                contactData.phoneNumbers.add(it)
                        }
                    }
                }

正如我所看到的,许多联系人都有相同的号码 2 或 3 次或 evan 4 次。我猜“问题”来自

retrieveAllContactNumbers()
,它从
ContactsContract.CommonDataKinds.Phone
获取数字。大多数情况下,我想知道为什么会发生这种情况,然后如何防止它?

我还注意到了这一点:我添加了一个假联系人,并且在我的列表中看到它有 2 个号码。也许这与 contentResolver 从哪里获取数字有关?例如 Google 帐户、SIM 卡、内部存储...?我不知道...

android android-contacts android-contentresolver
1个回答
0
投票

联系人数据库的组织方式符合预期:

  1. Contacts
    - 每个条目代表一个联系人,并将一个或多个组合在一起
    RawContacts
  2. RawContacts
    - 每个条目代表由某些
    SyncAdapter
    (例如 Whatsapp、Google、Facebook、Viber)同步的联系人数据,这对多个数据条目进行分组
  3. Data
    - 有关联系人、电子邮件、电话等的实际数据。每一行都是属于单个
    RawContact
  4. 的单个数据

您应该直接从

Data
表查询电话,因此您可能会从代表相同
RawContacts
的不同
Contact
获得相同的电话号码。

例如,如果您的设备上安装了 Whatsapp,并且 Google 正在同步您的联系人,则每个联系人可以并且将会存储相同的电话号码 2 个 RawContacts - 每个应用程序一个。

简单的解决方案是将您的地图更改为:

val contactsNumberMap = HashMap<String, Set<String>>()

Set
将强制每个联系人的电话列表具有唯一性。

© www.soinside.com 2019 - 2024. All rights reserved.