Aminul Haque Aome
Aminul Haque Aome

Reputation: 2609

Phone number search query not fetching number with country code In Android Content Provider

In my app, I want to implement a feature where I give a phone number and it provides all the info of that particular number saved in my phone using content provider. Here the code I tried. Partially it fulfilled what I want.

ContactRepository.kt

interface ContactRepository {
    suspend fun getContacts(mobileNumbers: List<String?>): Result<List<Contact>>
}

ContactRepositoryImpl.kt

class ContactRepositoryImpl @Inject constructor(
    @ApplicationContext private val context: Context
) : ContactRepository {


    override suspend fun getContacts(mobileNumbers: List<String?>): Result<List<Contact>> {
        val contactList = mutableListOf<Contact>()

        return runCatching {
            val contentResolver = context.contentResolver

            val uri = Phone.CONTENT_URI
            val projection = arrayOf(
                Phone.NUMBER,
                Phone.DISPLAY_NAME,
                Phone.PHOTO_URI
            )
            val selection = "${Phone.NUMBER} IN (${mobileNumbers.joinToString(",") { "?" }})"
            val selectionArgs = mobileNumbers.filterNotNull().toTypedArray()

            // SELECT `projection` FROM `uri` WHERE `selection` = `selectionArgs`
            val cursor = contentResolver.query(uri, projection, selection, selectionArgs, null)

            cursor?.use {
                val phoneNumberIndex = it.getColumnIndex(Phone.NUMBER)
                val nameIndex = it.getColumnIndex(Phone.DISPLAY_NAME)
                val photoUriIndex = it.getColumnIndex(Phone.PHOTO_URI)

                while (it.moveToNext()) {
                    val number = it.getString(phoneNumberIndex)
                    val name = it.getString(nameIndex)
                    val photoUri = it.getString(photoUriIndex)

                    println("Value -> $number : $name : $photoUri")

                    contactList.add(
                        Contact(
                            name = name,
                            number = number,
                            photoUri = photoUri
                        )
                    )
                }
            }

            contactList
        }
    }

}

But The problem arise when I give a number in input i.e (01866985338) and this number is saved in my phone along with country code i.e (+880186698 or +880 1866-98). That's why, although both are the same number, according to mismatch of my 'selection', it did not fetch that. How can I solved the issue.

Remember, Input can be list of String or a single string

Upvotes: 1

Views: 35

Answers (2)

Aminul Haque Aome
Aminul Haque Aome

Reputation: 2609

I found the solution. Here it is.

suspend fun getContacts(phoneNumbers: List<String>): List<Contact>? {
        val normalizedPhoneNumbers = phoneNumbers.map { PhoneNumberUtils.normalizeNumber(it) }

        val uri = Phone.CONTENT_URI
        val projection = arrayOf(
            Phone.NUMBER,
            Phone.DISPLAY_NAME,
            Phone.PHOTO_URI
        )

        val selection = normalizedPhoneNumbers.joinToString(" OR ") {
            "${Phone.NUMBER} LIKE ? OR ${Phone.NORMALIZED_NUMBER} LIKE ?"
        }
        val selectionArgs = normalizedPhoneNumbers.flatMap { listOf("%$it", "%$it") }.toTypedArray()

        return withContext(ioDispatcher) {
            val contactList = mutableListOf<Contact>()

            val cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)

            cursor?.use {
                val numberIndex = it.getColumnIndexOrThrow(Phone.NUMBER)
                val nameIndex = it.getColumnIndexOrThrow(Phone.DISPLAY_NAME)
                val photoUriIndex = it.getColumnIndexOrThrow(Phone.PHOTO_URI)

                while (it.moveToNext()) {
                    val number = it.getString(numberIndex)
                    val name = it.getString(nameIndex)
                    val photoUri = it.getString(photoUriIndex)

                    contactList.add(Contact(name, number, photoUri))
                }
            }

            return@withContext contactList.ifEmpty { null }
        }
    }

Upvotes: 0

Saiful Alam Rifan
Saiful Alam Rifan

Reputation: 476

To prevent this problem use PhoneNumberUtils.normalizeNumber(it) to normalize each phone number in the list. This method removes non-dialable characters (like spaces, and hyphens) and converts the number into a standardized format.

full code:

import android.telephony.PhoneNumberUtils

class ContactRepositoryImpl @Inject constructor(
    @ApplicationContext private val context: Context
) : ContactRepository {

    override suspend fun getContacts(mobileNumbers: List<String?>): Result<List<Contact>> {
        val contactList = mutableListOf<Contact>()

        return runCatching {
            val contentResolver = context.contentResolver

            val normalizedNumbers = mobileNumbers.mapNotNull { 
                it?.let { PhoneNumberUtils.normalizeNumber(it) } 
            }

            val uri = Phone.CONTENT_URI
            val projection = arrayOf(
                Phone.NUMBER,
                Phone.DISPLAY_NAME,
                Phone.PHOTO_URI
            )
            val selection = "${Phone.NUMBER} IN (${normalizedNumbers.joinToString(",") { "?" }})"
            val selectionArgs = normalizedNumbers.toTypedArray()

            val cursor = contentResolver.query(uri, projection, selection, selectionArgs, null)

            cursor?.use {
                val phoneNumberIndex = it.getColumnIndex(Phone.NUMBER)
                val nameIndex = it.getColumnIndex(Phone.DISPLAY_NAME)
                val photoUriIndex = it.getColumnIndex(Phone.PHOTO_URI)

                while (it.moveToNext()) {
                    val number = it.getString(phoneNumberIndex)
                    val name = it.getString(nameIndex)
                    val photoUri = it.getString(photoUriIndex)

                    println("Value -> $number : $name : $photoUri")

                    contactList.add(
                        Contact(
                            name = name,
                            number = number,
                            photoUri = photoUri
                        )
                    )
                }
            }

            contactList
        }
    }
}

Upvotes: 1

Related Questions