Novità sul prodotto
Selettore di contatti: condivisione dei contatti nel rispetto della privacy
Lettura di 4 minuti
La privacy e il controllo degli utenti rimangono al centro dell'esperienza Android. Proprio come il selettore di foto ha reso la condivisione di contenuti multimediali sicura e facile da implementare, ora stiamo portando lo stesso livello di privacy, semplicità e ottima esperienza utente alla selezione dei contatti.
Un nuovo standard per la privacy dei contatti
In passato, le applicazioni che richiedevano l'accesso ai contatti di un utente specifico si basavano sull'autorizzazione generica READ_CONTACTS. Sebbene funzionale, questo approccio spesso concedeva alle app più dati del necessario. Il nuovo selettore di contatti Android, introdotto in Android 17, cambia questa dinamica fornendo un'interfaccia standardizzata, sicura e ricercabile per la selezione dei contatti.
Questa funzionalità consente agli utenti di concedere alle app l'accesso solo ai contatti specifici che scelgono, in linea con l'impegno di Android per la trasparenza dei dati e le impronte delle autorizzazioni ridotte al minimo.
Come funziona
Gli sviluppatori possono integrare il Selettore di contatti utilizzando l'intent Intent.ACTION_PICK_CONTACTS. Questa API aggiornata offre diverse funzionalità avanzate:
- Richieste di dati granulari:le app possono specificare esattamente i campi di cui hanno bisogno, ad esempio numeri di telefono o indirizzi email, anziché ricevere l'intero record del contatto.
- Supporto della selezione multipla:il selettore supporta la selezione di uno o più contatti, offrendo agli sviluppatori maggiore flessibilità per funzionalità come gli inviti di gruppo.
- Limiti di selezione:gli sviluppatori possono impostare limiti personalizzati al numero di contatti che un utente può selezionare contemporaneamente.
- Accesso temporaneo:una volta selezionato, il sistema restituisce un URI di sessione che fornisce l'accesso in lettura temporaneo ai dati richiesti, garantendo che l'accesso non persista più del necessario.
- Accesso ad altri profili: quando utilizzi questo nuovo intent, l'interfaccia consente agli utenti di selezionare contenuti da altri profili utente, ad esempio un profilo di lavoro, un profilo clonato o uno spazio privato.
- Rendimento ottimizzato : il selettore di contatti restituisce un singolo URI che consente di eseguire query collettive sui risultati, eliminando la necessità di eseguire query individuali sugli URI dei contatti separatamente, come richiesto da
ACTION_PICK. Questa efficienza riduce ulteriormente l'overhead del sistema utilizzando una singola transazioneBinder.
Compatibilità con le versioni precedenti e implementazione
Per i dispositivi con Android 17 o versioni successive, il sistema esegue automaticamente l'upgrade degli intent ACTION_PICK legacy che specificano i tipi di dati di contatto alla nuova interfaccia più sicura. Tuttavia, per sfruttare appieno le funzionalità avanzate come la selezione multipla, gli sviluppatori sono invitati ad aggiornare il codice di implementazione e utilizzare ContentResolver per eseguire query sull'URI della sessione restituito.
Integra il selettore di contattiPer integrare il selettore di contatti, gli sviluppatori utilizzano l'intent ACTION_PICK_CONTACTS. Di seguito è riportato un esempio di codice che mostra come avviare il selettore e richiedere campi di dati specifici, come email e numeri di telefono.
// State to hold the list of selected contacts var contacts by remember { mutableStateOf<List>(emptyList()) } // Launcher for the Contact Picker intent val pickContact = rememberLauncherForActivityResult(StartActivityForResult()) { if (it.resultCode == Activity.RESULT_OK) { val resultUri = it.data?.data ?: return@rememberLauncherForActivityResult // Process the result URI in a background thread coroutine.launch { contacts = processContactPickerResultUri(resultUri, context) } } } // Define the specific contact data fields you need val requestedFields = arrayListOf( Email.CONTENT_ITEM_TYPE, Phone.CONTENT_ITEM_TYPE, ) // Set up the intent for the Contact Picker val pickContactIntent = Intent(ACTION_PICK_CONTACTS).apply { putExtra(EXTRA_PICK_CONTACTS_SELECTION_LIMIT, 5) putStringArrayListExtra( EXTRA_PICK_CONTACTS_REQUESTED_DATA_FIELDS, requestedFields ) putExtra(EXTRA_PICK_CONTACTS_MATCH_ALL_DATA_FIELDS, false) } // Launch the picker pickContact.launch(pickContactIntent)
Dopo che l'utente ha effettuato una selezione, l'app elabora il risultato eseguendo una query sull'URI della sessione restituito per estrarre i dati di contatto richiesti.
// Data class representing a parsed Contact with selected details data class Contact(val id: String, val name: String, val email: String?, val phone: String?) // Helper function to query the content resolver with the URI returned by the Contact Picker. // Parses the cursor to extract contact details such as name, email, and phone number private suspend fun processContactPickerResultUri( sessionUri: Uri, context: Context ): List<Contact> = withContext(Dispatchers.IO) { // Define the columns we want to retrieve from the ContactPicker ContentProvider val projection = arrayOf( ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.Data.MIMETYPE, // Type of data (e.g., email or phone) ContactsContract.Data.DATA1, // The actual data (Phone number / Email string) ) val results = mutableListOf<Contact>() // Note: The Contact Picker Session Uri doesn't support custom selection & selectionArgs. context.contentResolver.query(sessionUri, projection, null, null, null)?.use { cursor -> // Get the column indices for our requested projection val contactIdIdx = cursor.getColumnIndex(ContactsContract.Contacts._ID) val mimeTypeIdx = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE) val nameIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY) val data1Idx = cursor.getColumnIndex(ContactsContract.Data.DATA1) while (cursor.moveToNext()) { val contactId = cursor.getString(contactIdIdx) val mimeType = cursor.getString(mimeTypeIdx) val name = cursor.getString(nameIdx) ?: "" val data1 = cursor.getString(data1Idx) ?: "" // Determine if the current row represents an email or a phone number val email = if (mimeType == Email.CONTENT_ITEM_TYPE) data1 else null val phone = if (mimeType == Phone.CONTENT_ITEM_TYPE) data1 else null // Add the parsed contact to our results list results.add(Contact(contactId, name, email, phone)) } } return@withContext results }
Consulta la documentazione completa qui.
Best practice per gli sviluppatori
Per offrire la migliore esperienza utente e mantenere elevati standard di sicurezza, ti consigliamo di:
- Minimizzazione dei dati: richiedi solo i campi di dati specifici (ad es. email) di cui ha bisogno la tua app.
- Persistenza immediata:mantieni i dati selezionati immediatamente, poiché l'accesso all'URI della sessione è temporaneo.
Continua a leggere
-
Novità sul prodotto
Il selettore di foto incorporato: un modo più semplice per richiedere in privato foto e video nella tua app.
Roxanna Aliabadi Walker, Yacine Rezgui • Lettura di 8 minuti
-
Novità sul prodotto
Testare le interazioni multi-dispositivo è ora più facile che mai con l'emulatore Android.
Steven Jenkins • Lettura di 2 minuti
-
Novità sul prodotto
Android Studio supporta Gemma 4: il nostro modello locale più potente per la programmazione agentica
Il flusso di lavoro e le esigenze di ogni sviluppatore in materia di AI sono unici ed è importante poter scegliere in che modo l'AI può aiutarti nello sviluppo. A gennaio abbiamo introdotto la possibilità di scegliere qualsiasi modello di AI locale o remoto per potenziare la funzionalità di AI in Android Studio
Matthew Warner • Lettura di 2 minuti
Segui gli aggiornamenti
Ricevi ogni settimana gli ultimi approfondimenti sullo sviluppo per Android direttamente nella tua casella di posta.