Reputation: 2609
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
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
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