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_TYPEContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPEContactsContract.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.