Nowości dotyczące produktów
Selektor kontaktów: udostępnianie kontaktów z myślą o prywatności
Czas czytania: 4 minuty
Prywatność i kontrola użytkownika pozostają najważniejszymi elementami Androida. Podobnie jak selektor zdjęć, który sprawił, że udostępnianie multimediów stało się bezpieczne i łatwe do wdrożenia, teraz wprowadzamy ten sam poziom prywatności, prostoty i wygody użytkownika w przypadku wybierania kontaktów.
Nowy standard prywatności kontaktów
W przeszłości aplikacje wymagające dostępu do kontaktów konkretnego użytkownika korzystały z szerokiego uprawnienia READ_CONTACTS. Chociaż to podejście było funkcjonalne, często przyznawało aplikacjom więcej danych niż było to konieczne. Nowy selektor kontaktów na Androidzie, wprowadzony w Androidzie 17, zmienia tę dynamikę, udostępniając standardowy, bezpieczny i umożliwiający wyszukiwanie interfejs do wybierania kontaktów.
Ta funkcja pozwala użytkownikom przyznawać aplikacjom dostęp tylko do wybranych przez nich kontaktów, co jest zgodne z zobowiązaniem Androida do zapewnienia przejrzystości danych i zminimalizowania zakresu uprawnień.
Jak to działa
Deweloperzy mogą zintegrować selektor kontaktów za pomocą intencji Intent.ACTION_PICK_CONTACTS. Ten zaktualizowany interfejs API oferuje kilka zaawansowanych funkcji:
- Szczegółowe żądania danych: aplikacje mogą określać dokładnie, które pola są im potrzebne, np. numery telefonów lub adresy e-mail, zamiast otrzymywać cały rekord kontaktu.
- Obsługa wielokrotnego wyboru: selektor obsługuje wybieranie pojedynczych i wielu kontaktów, co daje deweloperom większą elastyczność w przypadku funkcji takich jak zaproszenia do grupy.
- Limity wyboru: deweloperzy mogą ustawiać niestandardowe limity liczby kontaktów, które użytkownik może wybrać jednocześnie.
- Dostęp tymczasowy: Po wybraniu system zwraca identyfikator URI sesji, który zapewnia tymczasowy dostęp do odczytu żądanych danych, dzięki czemu dostęp nie trwa dłużej niż to konieczne.
- Dostęp do innych profili: gdy użytkownik używa tej nowej intencji, interfejs umożliwia mu wybieranie treści z innych profili, np. profilu służbowego, sklonowanego profilu lub przestrzeni prywatnej.
- Zoptymalizowana wydajność: selektor kontaktów zwraca pojedynczy identyfikator URI, który umożliwia zbiorcze wysyłanie zapytań o wyniki, co eliminuje konieczność wysyłania zapytań o poszczególne identyfikatory URI kontaktów oddzielnie, jak to jest wymagane w przypadku
ACTION_PICK. Ta wydajność dodatkowo zmniejsza obciążenie systemu dzięki wykorzystaniu pojedynczej transakcjiBinder.
Zgodność wsteczna i implementacja
W przypadku urządzeń z Androidem 17 lub nowszym system automatycznie uaktualnia starsze intencje ACTION_PICK, które określają typy danych kontaktowych, do nowego, bezpieczniejszego interfejsu. Aby jednak w pełni wykorzystać funkcje zaawansowane, takie jak wielokrotny wybór, deweloperzy powinni zaktualizować kod implementacji i użyć ContentResolver do wysyłania zapytań o zwrócony identyfikator URI sesji.
Integracja selektora kontaktówAby zintegrować selektor kontaktów, deweloperzy używają intencji ACTION_PICK_CONTACTS. Poniżej znajdziesz przykład kodu, który pokazuje, jak uruchomić selektor i poprosić o konkretne pola danych, takie jak adres e-mail i numery telefonów.
// 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)
Gdy użytkownik dokona wyboru, aplikacja przetwarza wynik, wysyłając zapytanie o zwrócony identyfikator URI sesji, aby wyodrębnić żądane informacje kontaktowe.
// 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 }
Pełną dokumentację znajdziesz tutaj.
Sprawdzone metody dla deweloperów
Aby zapewnić użytkownikom jak najlepsze wrażenia i utrzymać wysokie standardy bezpieczeństwa, zalecamy:
- Minimalizację danych: proś tylko o te pola danych (np. adres e-mail), których potrzebuje Twoja aplikacja.
- Natychmiastowe utrwalanie: utrwalaj wybrane dane natychmiast, ponieważ dostęp do identyfikatora URI sesji jest tymczasowy.
Czytaj dalej
-
r.r.
Nowości dotyczące produktów
Selektor zdjęć wbudowany w aplikację: wygodniejszy sposób na prywatne żądanie zdjęć i filmów w aplikacji.
Roxanna Aliabadi Walker, Yacine Rezgui • Czas czytania: 8 min
-
Nowości dotyczące produktów
Ekosystem mobilny stale się rozwija, co stwarza nowe możliwości i nowe zagrożenia. W ramach tych zmian Android i Google Play nadal dokładają wszelkich starań, aby miliardy użytkowników mogły bezpiecznie korzystać z aplikacji, a deweloperzy mogli rozwijać innowacje.
Vijaya Kaza • Czas czytania: 3 min
-
r.r.
Nowości dotyczące produktów
Wersja Jetpack Compose z kwietnia 2026 r. jest stabilna. Ta wersja zawiera wersję 1.11 podstawowych modułów Compose (zobacz pełne mapowanie BOM), narzędzia do debugowania elementów wspólnych, zdarzenia trackpada i inne.
Meghan Mehta • Czas czytania: 5 min
Bądź na bieżąco
Otrzymuj co tydzień najnowsze informacje o tworzeniu aplikacji na Androida na swoją skrzynkę odbiorczą.