Obtaining Email Addresses of Specific Contact Without Permissions

168 Views Asked by At

I can easily get a list of every email address for every Contact using the following example snippets:

//...
private val getPerson = registerForActivityResult(PickContact()) {
        it?.also { contactUri ->
            val personDetails = ContactForPerson("", "", "")

            val projection = arrayOf(
                ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY,          //String
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY,//String
                ContactsContract.CommonDataKinds.Email.ADDRESS,             //String
            )

            context?.contentResolver?.query(contactUri, projection, null, null, null)?.apply {
                moveToFirst()
                personDetails.apply {
                    uri = getStringOrNull(0)
                    name = getString(1)
                    email = getStringOrNull(2)
                }
                close()
            }
        }
    }

//...

fab.setOnClickListener {
//...
          getPerson.launch(0)
//...
}

//...

class PickContact : ActivityResultContract<Int, Uri?>() {
    override fun createIntent(context: Context, input: Int?) =
            Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI).also {
                it.type = ContactsContract.CommonDataKinds.Email.CONTENT_TYPE
            }

    override fun parseResult(resultCode: Int, intent: Intent?): Uri? =
        if (resultCode == RESULT_OK) intent?.data else null
}

The question is, since I already have some information about a Contact, is there a way for me to filter the giant list of every email address for every Contact to only show me the email addresses for a single Contact?

I noticed Get specific contact information from URI returned from Intent.ACTION_PICK, but the information is rather dated and it's not clear if the READ_CONTACTS permission is required, which is not desired.

Thank you.

1

There are 1 best solutions below

0
On

It seems you're calling an EMAIL-PICKER and not a CONTACT-PICKER, by setting the intent type to Email.CONTENT_TYPE.

This means the user will be choosing a specific email in the device's default contacts app.

The result you're then getting from the picker is not a contactUri, rather a dataUri - i.e. a uri that points to a specific row in the Data table, which only allows you to get info about that specific row, in this case it must be an email row.

This also means your projection is a bit funny by using fields under CommonDataKinds.Phone.X, this doesn't matter too much as these fields are inherited from Data.CONTENT_URI, but to prevent confusion you should probably replace these with:

Data.LOOKUP_KEY, 
Data.DISPLAY_NAME_PRIMARY,
Email.ADDRESS,   

Now, if you want all the contact's email rather then a single one, you should not set the intent type - this will launch a contact picker which will allow you to get the contact's emails + phones + name by retrieving the Entity as shown here.