Home > front end >  Getting contact information from contact list with Kotlin
Getting contact information from contact list with Kotlin

Time:10-03

I'm trying to get some information about a contact that the user can select in the contact list, using Kotlin. I tried a couple tutorials that only worked partly. This is the code that should call startActivityForResult(), from MainActivity.kt:

add_contact.setOnClickListener {
    val intent = Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI)
    startActivityForResult(intent, CONTACT_PICK_CODE)
}

And the following is the overridden onActivityResult method:

@SuppressLint("Range")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    // handle intent results || calls when user from Intent (Contact Pick) picks or cancels pick contact
    if (resultCode == RESULT_OK) {
        if (requestCode == CONTACT_PICK_CODE) {
            val cursor1: Cursor
            val cursor2: Cursor?

            // get data from intent
            val uri = data!!.data
            cursor1 = contentResolver.query(uri!!, null, null, null, null)!!
            if (cursor1.moveToFirst()) {
                // get contact details
                val contactId = cursor1.getString(cursor1.getColumnIndex(ContactsContract.Contacts._ID))
                val contactName = cursor1.getString(cursor1.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))
                val contactThumbnail = cursor1.getString(cursor1.getColumnIndex(ContactsContract.Contacts.PHOTO_THUMBNAIL_URI))
                val idResults = cursor1.getString(cursor1.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))
                val idResultHold = idResults.toInt()
                // check if contact has a phone number or not
                if (idResultHold == 1) {
                    cursor2 = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI,
                    null,
                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID   " = "   contactId,
                    null,
                    null
                    )
                    // a contact may have multiple phone numbers
                    var contactNumber : String = ""
                    while (cursor2!!.moveToNext()) {
                        // get phone number
                        contactNumber = cursor2.getString(cursor2.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
                    }
                    Toast.makeText(this, "Contact number: $contactNumber", Toast.LENGTH_SHORT).show()
                    cursor2.close()
                }
                cursor1.close()
            }
        }
    } else {
        Toast.makeText(this, "Cancelled", Toast.LENGTH_SHORT).show()
    }
}

The line that prints "Contact number: ..." never prints the contact number, which means that the while loop never runs.

All the other variables (contactId, contactName...) seem to be assigned the correct value every time, but the number doesn't. Does anyone know what causes that to happen?

CodePudding user response:

Try this to get multiple phone numbers from a contact

const val REQUEST_SELECT_PHONE_NUMBER = 1

fun selectContact() {
    // Start an activity for the user to pick a phone number from contacts
    val intent = Intent(Intent.ACTION_PICK).apply {
        type = CommonDataKinds.Phone.CONTENT_TYPE
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivityForResult(intent, REQUEST_SELECT_PHONE_NUMBER)
    }
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    if (requestCode == REQUEST_SELECT_PHONE_NUMBER && resultCode == Activity.RESULT_OK) {
        // Get the URI and query the content provider for the phone number
        val contactUri: Uri = data.data
        val projection: Array<String> = arrayOf(CommonDataKinds.Phone.NUMBER)
        contentResolver.query(contactUri, projection, null, null, null).use { cursor ->
            // If the cursor returned is valid, get the phone number
            if (cursor.moveToFirst()) {
                val numberIndex = cursor.getColumnIndex(CommonDataKinds.Phone.NUMBER)
                val number = cursor.getString(numberIndex)
                // Do something with the phone number
                ...
            }
        }
    }
}

CodePudding user response:

cursor2 = > contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, ...

To return the phone numbers you need to replace the ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI Uri with ContactsContract.CommonDataKinds.Phone.CONTENT_URI

Instead of using a String, you can use a Set to have no duplicate numbers, because; this URI returns all the links to the phone numbers besides the phone storage; like Google, WhatsApp, .. etc.

@SuppressLint("Range")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    // handle intent results || calls when user from Intent (Contact Pick) picks or cancels pick contact
    if (resultCode == RESULT_OK) {
        if (requestCode == CONTACT_PICK_CODE) {
            val cursor1: Cursor
            val cursor2: Cursor?

            // get data from intent
            val uri = data!!.data
            cursor1 = contentResolver.query(uri!!, null, null, null, null)!!

            if (cursor1.moveToFirst()) {
                // get contact details
                val contactId =
                    cursor1.getString(cursor1.getColumnIndex(ContactsContract.Contacts._ID))
                val contactName =
                    cursor1.getString(cursor1.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))
                val contactThumbnail =
                    cursor1.getString(cursor1.getColumnIndex(ContactsContract.Contacts.PHOTO_THUMBNAIL_URI))
                val idResults =
                    cursor1.getString(cursor1.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))
                val idResultHold = idResults.toInt()
                // check if contact has a phone number or not
                if (idResultHold == 1) {
                    cursor2 = contentResolver.query(
//                            ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, // WRONG
                        ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                        null,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID   " = "   contactId,
                        null,
                        null
                    )

                    // a contact may have multiple phone numbers
                    val numbers = mutableSetOf<String>()
                    cursor2?.let {
                        while (cursor2.moveToNext()) {
                            val phoneNumber =
                                cursor2.getString(
                                    cursor2.getColumnIndex(
                                        ContactsContract.CommonDataKinds.Phone.NUMBER
                                    )
                                ).replace("-", "").replace(
                                    " ",
                                    ""
                                )  // Remove the dash sign & spaces from the numbers

                            numbers.add(phoneNumber)
                        }
                        Toast.makeText(
                            this@MainActivity,
                            "$contactName $numbers",
                            Toast.LENGTH_LONG
                        ).show()

                        cursor2.close()
                    }
                    cursor1.close()
                }
            }


        }
    } else {
        Toast.makeText(this, "Cancelled", Toast.LENGTH_SHORT).show()
    }
}

Note: you're using a deprecated API onActivityResult that is replaced with registerForActivityResult

Here is a demo of using it:

class MainActivity : AppCompatActivity() {

    private val requestSinglePermission =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
            // Do something if permission granted
            if (isGranted) {
                Log.d("LOG_TAG", "permission granted by the user")

                // Do something as the permission is not granted
            } else {
                Log.d("LOG_TAG", "permission denied by the user")
            }
        }


    private var allNumLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                // There are no request codes
                val data = result.data?.data

                data?.let {
                    val cursor = contentResolver.query(
                        data,
                        null,
                        null,
                        null,
                        null
                    )

                    cursor?.let {
                        if (it.moveToFirst()) {
                            val name =
                                it.getString(it.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME))

                            if (Integer.parseInt(
                                    it.getString(
                                        it.getColumnIndex(
                                            ContactsContract.Contacts.HAS_PHONE_NUMBER
                                        )
                                    )
                                ) > 0 // Check if the contact has phone numbers
                            ) {

                                val id =
                                    it.getString(it.getColumnIndex(ContactsContract.Contacts._ID))

                                val phonesCursor = contentResolver.query(
                                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                                    null,
                                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID   " = "   id,
                                    null,
                                    null
                                )

                                val numbers = mutableSetOf<String>()
                                phonesCursor?.let {
                                    while (phonesCursor.moveToNext()) {
                                        val phoneNumber =
                                            phonesCursor.getString(
                                                phonesCursor.getColumnIndex(
                                                    ContactsContract.CommonDataKinds.Phone.NUMBER
                                                )
                                            ).replace("-", "").replace(" ", "")
                                        numbers.add(phoneNumber)
                                    }
                                    Toast.makeText(
                                        this@MainActivity,
                                        "$name $numbers",
                                        Toast.LENGTH_LONG
                                    ).show()
                                    Log.d(TAG, "$name $numbers")
                                }

                                phonesCursor?.close()

                            } else {
                                Toast.makeText(
                                    this@MainActivity,
                                    "$name - No numbers",
                                    Toast.LENGTH_LONG
                                ).show()
                                Log.d(TAG, "$name - No numbers")
                            }
                        }

                        cursor.close()
                    }

                }
            }
        }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.READ_CONTACTS
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            requestSinglePermission.launch(
                Manifest.permission.READ_CONTACTS
            )

        }


        // get a contact:
        val intent = Intent(Intent.ACTION_PICK,
                ContactsContract.Contacts.CONTENT_URI) 
        allNumLauncher.launch(intent)

    }
}
  • Related