Trình chọn người liên hệ của Android là một giao diện tiêu chuẩn, có thể duyệt để người dùng chia sẻ thông tin liên hệ với ứng dụng của bạn. Trình chọn này có trên các thiết bị chạy Android 17 (cấp độ API 37) trở lên và cung cấp một giải pháp thay thế giúp đảm bảo quyền riêng tư cho quyền READ_CONTACTS rộng. Thay vì yêu cầu quyền truy cập vào toàn bộ sổ địa chỉ của người dùng, ứng dụng của bạn sẽ chỉ định các trường dữ liệu mà ứng dụng cần, chẳng hạn như số điện thoại hoặc địa chỉ email, và người dùng sẽ chọn những người liên hệ cụ thể để chia sẻ. Điều này cấp cho ứng dụng của bạn quyền truy cập chỉ đọc vào dữ liệu đã chọn, đảm bảo kiểm soát chi tiết trong khi mang đến trải nghiệm nhất quán cho người dùng với các tính năng tìm kiếm, chuyển đổi hồ sơ và chọn nhiều người liên hệ được tích hợp sẵn mà không cần xây dựng hoặc duy trì giao diện người dùng.
Tích hợp Trình chọn người liên hệ
Để tích hợp Trình chọn người liên hệ, hãy sử dụng ý định Intent.ACTION_PICK_CONTACTS.
Ý định này sẽ khởi chạy trình chọn và trả về những người liên hệ đã chọn cho ứng dụng của bạn.
Không giống như ACTION_PICK cũ, Trình chọn người liên hệ cho phép bạn chỉ định nhiều trường dữ liệu mà ứng dụng yêu cầu cùng một lúc. Bạn thực hiện việc này bằng cách sử dụng
Intent.EXTRA_REQUESTED_DATA_FIELDS, truyền một ArrayList<String> gồm các loại MIME
được xác định trong ContactsContract.CommonDataKinds.
Các loại MIME phổ biến bao gồm:
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPEContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPEContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE
Khởi chạy trình chọn
Sử dụng registerForActivityResult với hợp đồng StartActivityForResult để khởi chạy trình chọn. Bạn có thể định cấu hình ý định để cho phép chọn một hoặc nhiều người liên hệ.
Chọn một người liên hệ
Trong ví dụ này, ứng dụng chỉ yêu cầu số điện thoại. Trình chọn sẽ lọc danh sách để chỉ hiển thị những người liên hệ có số điện thoại và cho phép người dùng chọn một số cụ thể.
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);
Chọn nhiều người liên hệ
Để bật tính năng chọn nhiều người liên hệ, hãy thêm phần bổ sung Intent.EXTRA_ALLOW_MULTIPLE. Bạn có thể tuỳ ý giới hạn số lượng mục mà người dùng có thể chọn.
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)
Xử lý kết quả
Khi người dùng hoàn tất việc chọn, hệ thống sẽ trả về RESULT_OK và URI phiên. URI này cấp quyền truy cập tạm thời để đọc dữ liệu đã chọn.
Bạn có thể truy vấn URI này bằng cách sử dụng ContentResolver tiêu chuẩn. Cursor kết quả chứa các trường dữ liệu được yêu cầu và tuân theo giản đồ của 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")
}
}
}
}
}
Khả năng tương thích ngược
Đối với các ứng dụng nhắm đến Android 17 (cấp độ API 37) trở lên, hệ thống sẽ tự động nâng cấp ý định Intent.ACTION_PICK hiện có để sử dụng giao diện Trình chọn người liên hệ mới.
Nếu ứng dụng của bạn đã sử dụng ACTION_PICK, thì bạn không cần thay đổi mã để nhận giao diện người dùng mới. Tuy nhiên, để tận dụng các tính năng mới, chẳng hạn như nhận một Uri duy nhất để truy vấn dữ liệu liên hệ, chuyển đổi giữa hồ sơ cá nhân và hồ sơ công việc hoặc nhiều yêu cầu trường dữ liệu, bạn phải cập nhật quá trình triển khai để sử dụng Intent.ACTION_PICK_CONTACTS hoặc các phần bổ sung ý định mới.
Kiểm thử trên các SDK cũ
Bạn có thể kiểm thử hành vi của trình chọn mới trên các thiết bị chạy Android 17 trở lên ngay cả khi ứng dụng của bạn nhắm đến phiên bản SDK thấp hơn bằng cách thêm phần bổ sung boolean EXTRA_USE_SYSTEM_CONTACTS_PICKER vào ý định ACTION_PICK.
Các phương pháp hay nhất
- Chỉ yêu cầu những gì bạn cần: Nếu ứng dụng của bạn chỉ cần gửi tin nhắn SMS,
hãy yêu cầu
Phone.CONTENT_ITEM_TYPE. Trình chọn sẽ tự động lọc những người liên hệ không có số điện thoại, giúp giao diện người dùng trở nên gọn gàng hơn cho người dùng. - Lưu giữ dữ liệu ngay lập tức: URI phiên cấp quyền đọc tạm thời quyền. Nếu cần truy cập vào thông tin liên hệ này sau đó (sau khi quá trình của ứng dụng bị huỷ), thì ứng dụng của bạn phải lưu giữ dữ liệu liên hệ.
- Không dựa vào Dữ liệu tài khoản: Để bảo vệ quyền riêng tư của người dùng và ngăn chặn việc tạo vân tay số, siêu dữ liệu dành riêng cho tài khoản sẽ bị xoá khỏi kết quả.