Novità sui prodotti
Selettore di contatti: condivisione dei contatti con la privacy al primo posto
Lettura di 4 minuti
La privacy e il controllo da parte degli utenti rimangono al centro dell'esperienza Android. Proprio come il selettore di foto ha reso la condivisione dei 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
Storicamente, le applicazioni che richiedono l'accesso ai contatti di un utente specifico si basavano sull'autorizzazione READ_CONTACTS generale. 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 la riduzione al minimo delle autorizzazioni.
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 di contatto.
- Supporto per la selezione multipla: il selettore supporta la selezione di uno o più contatti, offrendo agli sviluppatori una 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: al momento della selezione, il sistema restituisce un URI di sessione che fornisce l'accesso in lettura temporaneo ai dati richiesti, assicurando che l'accesso non persista più del necessario.
- Accesso ad altri profili: quando si utilizza questo nuovo intent, l'interfaccia consentirà agli utenti di selezionare i contenuti di altri profili utente, ad esempio un profilo di lavoro, un profilo clonato o uno spazio privato.
- Prestazioni ottimizzate: il Selettore di contatti restituisce un singolo URI che consente di eseguire query collettive sui risultati, eliminando la necessità di eseguire query separate sugli URI dei singoli contatti come richiesto da
ACTION_PICK. Questa efficienza riduce ulteriormente il sovraccarico 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 a utilizzare ContentResolver per eseguire query sull'URI di 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 query sull'URI di sessione restituito per estrarre le informazioni di contatto richieste.
// 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:
- Minimizzare i dati: richiedi solo i campi di dati specifici (ad es. email) di cui la tua app ha bisogno.
- Persistenza immediata: rendi persistenti i dati selezionati immediatamente, poiché l'accesso all'URI di sessione è temporaneo.
Continua a leggere
-
Novità sui prodotti
Il selettore di foto incorporato: un modo più semplice per richiedere foto e video in privato nella tua app.
Roxanna Aliabadi Walker, Yacine Rezgui • Lettura di 8 minuti
-
Novità sui prodotti
Siamo felici di annunciare che è arrivato il supporto ufficiale per Unreal Engine e Godot per Android XR. Stiamo anche lanciando nuovi strumenti progettati per aumentare la produttività e abilitare nuove funzionalità XR: Android XR Engine Hub e Android XR Interaction Framework.
Luke Hopkins • Lettura di 4 minuti
-
Novità sui prodotti
Con il rilascio di Android 17, stiamo passando a uno standard di sviluppo adattivo. Gli utenti non si affidano più a un singolo fattore di forma, ma passano da smartphone, dispositivi pieghevoli, tablet, laptop, display per auto e ambienti XR immersivi durante la giornata.
Fahd Imtiaz • Lettura di 4 minuti
Resta al passo con le novità
Ricevi settimanalmente nella tua casella di posta gli ultimi approfondimenti sullo sviluppo di Android.