Инструмент выбора контактов: безопасный обмен контактными данными
Время на чтение: 4 минуты
Конфиденциальность и управление данными остаются ключевыми принципами работы Android. Как и в случае с окном выбора фотографий, мы стремимся обеспечить высокий уровень конфиденциальности, простоту использования и удобство для пользователей при выборе контактов.
Новый стандарт конфиденциальности контактных данных
Раньше приложения, которым требовался доступ к контактам определенного пользователя, полагались на широкое разрешение READ_CONTACTS. Такой подход был функциональным, но часто предоставлял приложениям больше данных, чем им было нужно. Новый инструмент выбора контактов в Android, представленный в Android 17, меняет эту динамику, предоставляя стандартизированный, безопасный и удобный для поиска интерфейс выбора контактов.
Эта функция позволяет пользователям предоставлять приложениям доступ только к выбранным контактам, что соответствует принципам прозрачности данных и минимального количества разрешений, принятым в Android.
Как это работает
Разработчики могут интегрировать инструмент выбора контактов с помощью интента Intent.ACTION_PICK_CONTACTS. Обновленный API предлагает следующие возможности:
- Запросы с высокой детализацией. Приложения могут указывать, какие именно поля им нужны, например номера телефонов или адреса электронной почты, а не получать всю запись о контакте.
- Поддержка выбора нескольких объектов. Инструмент позволяет выбирать как один, так и несколько контактов, что дает разработчикам больше возможностей для реализации таких функций, как приглашения в группы.
- Ограничения на выбор. Разработчики могут задавать ограничения на количество контактов, которые пользователь может выбрать за один раз.
- Временный доступ. После выбора этого варианта система возвращает URI сеанса, который предоставляет временный доступ на чтение к запрошенным данным. Это гарантирует, что доступ не будет сохраняться дольше, чем необходимо.
- Доступ к другим профилям. С помощью этого нового интента интерфейс позволит пользователям выбирать контент из других профилей пользователей, например рабочего профиля, клонированного профиля или частного пространства.
- Оптимизированная производительность. Инструмент выбора контактов возвращает один URI, который позволяет запрашивать результаты коллективно. Это устраняет необходимость запрашивать отдельные URI контактов, как требуется в
ACTION_PICK. Это позволяет снизить нагрузку на систему, поскольку используется одна транзакцияBinder.
Обратная совместимость и реализация
На устройствах с Android 17 или более поздней версии система автоматически преобразует устаревшие намерения ACTION_PICK, в которых указаны типы данных контактов, в новый, более безопасный интерфейс. Однако, чтобы использовать все возможности продвинутых функций, например множественный выбор, разработчикам рекомендуется обновить код и использовать ContentResolver для запроса возвращенного URI сеанса.
Как интегрировать инструмент выбора контактовДля этого разработчики используют интент ACTION_PICK_CONTACTS. Ниже приведен пример кода, демонстрирующий, как запустить выборщик и запросить определенные поля данных, например адреса электронной почты и номера телефонов.
// 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)
После того как пользователь сделает выбор, приложение обрабатывает результат, запрашивая возвращенный URI сеанса, чтобы извлечь запрошенную контактную информацию.
// 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 }
Ознакомьтесь с полной документацией здесь.
Рекомендации для разработчиков
Чтобы обеспечить удобство пользователей и высокий уровень безопасности, рекомендуем следующее:
- Минимизация данных. Запрашивайте только те поля данных (например, адрес электронной почты), которые необходимы вашему приложению.
- Немедленное сохранение. Сохраняйте выбранные данные немедленно, так как доступ к URI сеанса временный.
-
Новости продуктовВстроенный выбор фотографий. Более удобный способ запрашивать фотографии и видео в приложении с сохранением конфиденциальности.
Roxanna Aliabadi Walker, Yacine Rezgui • Время на чтение: 8 минут -
Новости продуктовМы постоянно расширяем возможности платформы подписок в Google Play, чтобы помочь вам развивать бизнес, адаптироваться к новым бизнес-моделям и привлекать пользователей.
Sheenam Mittal • Время на чтение: 4 минуты -
Новости продуктовВ прошлом году мы открыли Android Studio для любых моделей ИИ. Сегодня мы делаем следующий шаг и добавляем поддержку агентов для написания кода.
Matthew Warner • Время на чтение: 3 минуты
Получайте свежие новости о разработке приложений для Android на свою электронную почту каждую неделю.