Selettore contatti

Il selettore di contatti Android è un'interfaccia standardizzata e sfogliabile che consente agli utenti di condividere i contatti con la tua app. Disponibile sui dispositivi con Android 17 o versioni successive, il selettore offre un'alternativa che tutela la privacy all'ampia autorizzazione READ_CONTACTS. Anziché richiedere l'accesso all'intera rubrica dell'utente, la tua app specifica i campi di dati di cui ha bisogno, ad esempio numeri di telefono o indirizzi email, e l'utente seleziona contatti specifici da condividere. In questo modo, la tua app ottiene l'accesso in lettura solo ai dati selezionati, garantendo un controllo granulare e fornendo un'esperienza utente coerente con funzionalità di ricerca, cambio profilo e selezione multipla integrate senza dover creare o gestire la UI.

Integrare il selettore contatti

Per integrare il selettore di contatti, utilizza l'intent Intent.ACTION_PICK_CONTACTS. Questo intent avvia il selettore e restituisce i contatti selezionati alla tua app.

A differenza del selettore di contatti legacy ACTION_PICK, il selettore di contatti ti consente di specificare più campi di dati richiesti dalla tua app contemporaneamente. A tale scopo, utilizza Intent.EXTRA_REQUESTED_DATA_FIELDS, passando un ArrayList<String> di tipi MIME definiti in ContactsContract.CommonDataKinds.

I tipi MIME comuni includono:

  • ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
  • ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE
  • ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE

Avviare il selettore

Utilizza registerForActivityResult con il contratto StartActivityForResult per avviare il selettore. Puoi configurare l'intent in modo da consentire selezioni singole o multiple.

Selezionare un singolo contatto

In questo esempio, l'app richiede solo numeri di telefono. Il selettore filtrerà l'elenco per mostrare solo i contatti con numeri di telefono e consentirà all'utente di selezionare un numero specifico.

Kotlin

// Define the specific data fields you need
val requestedFields = arrayListOf(
    ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
)

// Set up the intent
val pickContactIntent = Intent(Intent.ACTION_PICK_CONTACTS).apply {
    type = ContactsContract.Contacts.CONTENT_TYPE
    putStringArrayListExtra(Intent.EXTRA_REQUESTED_DATA_FIELDS, requestedFields)
}

// Launch the picker
pickContactLauncher.launch(pickContactIntent)

Java

// Define the specific data fields you need
ArrayList<String> requestedFields = new ArrayList<>();
requestedFields.add(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);

// Set up the intent
Intent pickContactIntent = new Intent(Intent.ACTION_PICK_CONTACTS);
pickContactIntent.setType(ContactsContract.Contacts.CONTENT_TYPE);
pickContactIntent.putStringArrayListExtra(Intent.EXTRA_REQUESTED_DATA_FIELDS,
        requestedFields);

// Launch the picker
pickContactLauncher.launch(pickContactIntent);

Selezionare più contatti

Per attivare la selezione multipla, aggiungi l'extra Intent.EXTRA_ALLOW_MULTIPLE. Se vuoi, puoi limitare il numero di elementi che un utente può selezionare.

Kotlin

val requestedFields = arrayListOf(
    ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
    ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
)

val pickMultipleIntent = Intent(Intent.ACTION_PICK_CONTACTS).apply {
    type = ContactsContract.Contacts.CONTENT_TYPE
    putStringArrayListExtra(Intent.EXTRA_REQUESTED_DATA_FIELDS, requestedFields)
    // Enable multi-select
    putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
    // Optional: Set a custom limit (max 50 recommended)
    putExtra(Intent.EXTRA_SELECTION_LIMIT, 10)
}

pickMultipleLauncher.launch(pickMultipleIntent)

Gestire i risultati

Quando l'utente completa la selezione, il sistema restituisce un RESULT_OK e un URI di sessione. Questo URI concede l'accesso temporaneo in lettura ai dati selezionati.

Puoi eseguire query su questo URI utilizzando un ContentResolver standard. Il Cursor risultante contiene i campi di dati richiesti e segue lo schema di ContactsContract.Data.

Kotlin

private val pickContactLauncher = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        // The result data contains the Session URI
        val sessionUri = result.data?.data
        sessionUri?.let { uri ->
            processSelectedContacts(uri)
        }
    } else {
        // User cancelled the picker
    }
}

private fun processSelectedContacts(sessionUri: Uri) {
    // Define the projection (columns) you want to retrieve
    val projection = arrayOf(
        ContactsContract.Data.CONTACT_ID,
        ContactsContract.Contacts.DISPLAY_NAME_PRIMARY,
        ContactsContract.Data.MIMETYPE,
        ContactsContract.Data.DATA1 // Generic data column (Phone number, Email, etc.)
    )

    contentResolver.query(sessionUri, projection, null, null, null)?.use { cursor ->
        val mimeTypeIdx = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)
        val dataIdx = cursor.getColumnIndex(ContactsContract.Data.DATA1)
        val nameIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY)

        while (cursor.moveToNext()) {
            val mimeType = cursor.getString(mimeTypeIdx)
            val dataValue = cursor.getString(dataIdx)
            val name = cursor.getString(nameIdx)

            when (mimeType) {
                ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE -> {
                    Log.d("ContactPicker", "Picked Phone: $dataValue for $name")
                }
                ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE -> {
                    Log.d("ContactPicker", "Picked Email: $dataValue for $name")
                }
            }
        }
    }
}

Compatibilità con le versioni precedenti

Per le app che hanno come target Android 17 e versioni successive, il sistema aggiorna automaticamente l'intent Intent.ACTION_PICK esistente per utilizzare la nuova interfaccia del selettore di contatti.

Se la tua app utilizza già ACTION_PICK, non devi modificare il codice per ricevere la nuova UI. Tuttavia, per usufruire di nuove funzionalità, come ricevere un singolo Uri per eseguire query sui dati di contatto, passare da un profilo personale a uno di lavoro o richiedere più campi di dati, devi aggiornare l'implementazione per utilizzare Intent.ACTION_PICK_CONTACTS o i nuovi extra intent.

Test su SDK precedenti

Puoi testare il nuovo comportamento del selettore sui dispositivi con Android 17 e versioni successive anche se la tua app ha come target una versione dell'SDK precedente aggiungendo l'extra EXTRA_USE_SYSTEM_CONTACTS_PICKER booleano all'intent ACTION_PICK.

Best practice

  • Richiedi solo ciò di cui hai bisogno: se la tua app deve solo inviare un SMS, richiedi Phone.CONTENT_ITEM_TYPE. Il selettore filtrerà automaticamente i contatti che non hanno numeri di telefono, in modo da offrire un'interfaccia utente più pulita all'utente.
  • Rendi persistenti i dati immediatamente: l'URI di sessione concede l'autorizzazione di lettura temporanea. Se devi accedere a queste informazioni di contatto in un secondo momento (dopo l'interruzione del processo dell'app), l'app deve conservare i dati di contatto.
  • Non fare affidamento sui dati dell'account: per proteggere la privacy degli utenti ed evitare l'identificazione univoca del dispositivo, i metadati specifici dell'account vengono rimossi dai risultati.