Pick Contact - Android Studio - Compose

Implement the Contact Pick feature in and Android App

To allow the user to pick a contact from the phone's contacts list, we can use contact intent. You will get all information of the contact e.g. Name, Phone Number(s), Address, Thumbnail, Email, etc. You can use get the specific information according to your requirement. To pick a contact we need to READ_CONTACTS permission.


Code:

Add permission in AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.blogspot.atifsoftwares.pickcontact">

    <!--Read contact permission-->
    <uses-permission android:name="android.permission.READ_CONTACTS"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.PickContact">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

MainActivity.kt

package com.technifysoft.myapplication

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.provider.ContactsContract
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import coil.compose.rememberAsyncImagePainter
import com.technifysoft.myapplication.ui.theme.MyApplicationTheme

class MainActivityCompose : ComponentActivity() {

    private val requestPermissionLauncher =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
            if (isGranted) pickContact() else Toast.makeText(this, "Permission denied...", Toast.LENGTH_SHORT).show()
        }

    private val contactPickerLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == RESULT_OK) handleContactResult(result.data)
            else Toast.makeText(this, "No contact selected...", Toast.LENGTH_SHORT).show()
        }

    private var contactInfo by mutableStateOf("")
    private var contactThumbnailUri by mutableStateOf<Uri?>(null)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            ContactPickerScreen(
                thumbnailUri = contactThumbnailUri,
                contactInfo = contactInfo,
                onPickContactClick = {
                    if (checkContactPermission()) pickContact()
                    else requestContactPermission()
                }
            )
        }
    }

    private fun checkContactPermission(): Boolean =
        ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) ==
                PackageManager.PERMISSION_GRANTED

    private fun requestContactPermission() {
        requestPermissionLauncher.launch(Manifest.permission.READ_CONTACTS)
    }

    private fun pickContact() {
        val intent = Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI)
        contactPickerLauncher.launch(intent)
    }

    private fun handleContactResult(data: Intent?) {
        if (data == null) return
        val uri = data.data ?: return
        val cursor1 = contentResolver.query(uri, null, null, null, null)
        if (cursor1 != null && cursor1.moveToFirst()) {
            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 hasPhone = cursor1.getInt(cursor1.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))

            var info = "ID: $contactId\nName: $contactName"

            if (hasPhone == 1) {
                val phoneCursor = contentResolver.query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null,
                    "${ContactsContract.CommonDataKinds.Phone.CONTACT_ID} = ?",
                    arrayOf(contactId),
                    null
                )
                while (phoneCursor?.moveToNext() == true) {
                    val phone = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
                    info += "\nPhone: $phone"
                }
                phoneCursor?.close()
            }

            contactInfo = info
            contactThumbnailUri = contactThumbnail?.toUri()

            cursor1.close()
        }
    }
}

@Composable
fun ContactPickerScreen(
    thumbnailUri: Uri? = null,
    contactInfo: String = "",
    onPickContactClick: () -> Unit
) {
    Box(
        modifier = Modifier
            .fillMaxSize()
            .padding(10.dp)
    ) {
        Column(
            modifier = Modifier
                .align(Alignment.TopCenter)
                .padding(top = 20.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            // ImageView equivalent
            Image(
                painter = if (thumbnailUri != null)
                    rememberAsyncImagePainter(thumbnailUri)
                else
                    painterResource(id = R.drawable.ic_person),
                contentDescription = "Contact Thumbnail",
                modifier = Modifier
                    .size(120.dp)
                    .clip(CircleShape)
            )

            Spacer(modifier = Modifier.height(10.dp))

            // TextView equivalent
            Text(
                text = contactInfo.ifEmpty { "No contact selected" },
                modifier = Modifier.fillMaxWidth(),
                textAlign = TextAlign.Start
            )
        }

        // FloatingActionButton equivalent
        FloatingActionButton(
            onClick = { onPickContactClick() },
            modifier = Modifier
                .align(Alignment.BottomEnd)
                .padding(16.dp)
        ) {
            Icon(
                painter = painterResource(id = R.drawable.ic_person_add),
                contentDescription = "Pick Contact"
            )
        }
    }
}


/**
 * GreetingPreview is a composable function for previewing the MainUI in Android Studio.
 * It is annotated with @Preview to enable live preview.
 *
 */
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    MyApplicationTheme {
        ContactPickerScreen(
            null,
            "",
            onPickContactClick = {}
        )
    }
}

Screenshots

Pick Contact | Android Studio | Java
Pick Contact | Android Studio | Java

Comments

Popular posts from this blog

Picture In Picture | Android Studio | Kotlin

Manage External Storage Permission - Android Studio - Kotlin

How to add AIDL folder | Android Studio