Android Kişi Seçici, kullanıcıların kişilerle ilgili bilgileri uygulamanızla paylaşması için standartlaştırılmış ve gözatılabilir bir arayüzdür. Android 17 (API düzeyi 37) veya sonraki sürümlerin yüklü olduğu cihazlarda kullanılabilen seçici, geniş kapsamlı READ_CONTACTS iznine gizliliği korumaya yönelik bir alternatif sunar. Uygulamanız, kullanıcının tüm adres defterine erişim isteğinde bulunmak yerine ihtiyaç duyduğu veri alanlarını (ör. telefon numaraları veya e-posta adresleri) belirtir ve kullanıcı, paylaşılacak belirli kişileri seçer. Bu sayede uygulamanız yalnızca seçilen verilere okuma erişimi kazanır. Böylece, kullanıcı arayüzünü oluşturmak veya bakımını yapmak zorunda kalmadan yerleşik arama, profil değiştirme ve çoklu seçim özellikleri sayesinde tutarlı bir kullanıcı deneyimi sunarken ayrıntılı kontrol de sağlanır.
Kişi seçiciyi entegre etme
Kişi seçiciyi entegre etmek için Intent.ACTION_PICK_CONTACTS amacını kullanın.
Bu amaç, seçiciyi başlatır ve seçilen kişileri uygulamanıza döndürür.
Eski ACTION_PICK'dan farklı olarak, Kişi Seçici, uygulamanızın gerektirdiği birden fazla veri alanını aynı anda belirtmenize olanak tanır. Bunu, Intent.EXTRA_REQUESTED_DATA_FIELDS kullanarak yaparsınız. ContactsContract.CommonDataKinds içinde tanımlanan MIME türlerinin ArrayList<String>'sini iletirsiniz.
Yaygın MIME türleri şunlardır:
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPEContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPEContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE
Seçiciyi başlatma
Seçiciyi başlatmak için registerForActivityResult tuşunu StartActivityForResult sözleşmesiyle birlikte kullanın. Amacı, tek veya birden çok seçime izin verecek şekilde yapılandırabilirsiniz.
// 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 to fetch all selected contacts
coroutine.launch {
contacts = processContactPickerResultUri(resultUri, context)
}
}
}
Seçim modu
Kişi seçicinin kullanıcı arayüzü, istenen veri alanlarına göre ayarlanır. Bu şartlara bağlı olarak, birden fazla alan gerektiğinde kullanıcılar tüm kişi kaydını seçebilir veya bir kişinin bilgilerindeki belirli veri öğelerini seçebilir.
Tek bir kişi seçme
Bu örnekte uygulama yalnızca telefon numarası istiyor. Seçici, listede yalnızca telefon numarası olan kişileri gösterecek şekilde filtreleme yapar ve kullanıcının belirli bir numarayı seçmesine olanak tanır.
// 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 {
putStringArrayListExtra(
EXTRA_PICK_CONTACTS_REQUESTED_DATA_FIELDS,
requestedFields
)
}
// Launch the picker
pickContact.launch(pickContactIntent)
Birden fazla kişi seçme
Çoklu seçimi etkinleştirmek için Intent.EXTRA_ALLOW_MULTIPLE ekleyin. İsteğe bağlı olarak, kullanıcının seçebileceği öğe sayısını sınırlayabilirsiniz.
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 {
// Enable multi-select
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
// Set limit of selectable contacts
putExtra(EXTRA_PICK_CONTACTS_SELECTION_LIMIT, 5)
// Define the specific contact data fields you need
putStringArrayListExtra(
EXTRA_PICK_CONTACTS_REQUESTED_DATA_FIELDS,
requestedFields
)
// Enable this option to only filter contacts that have all the requested data fields
putExtra(EXTRA_PICK_CONTACTS_MATCH_ALL_DATA_FIELDS, false)
}
// Launch the picker
pickContact.launch(pickContactIntent)
Sonuçları işleme
Kullanıcı seçimi tamamladığında sistem RESULT_OK ve oturum URI'si döndürür. Bu URI, seçilen verilere geçici okuma erişimi verir.
Bu URI'yi standart bir ContentResolver kullanarak sorgulayabilirsiniz. Sonuçta elde edilen Cursor, istenen veri alanlarını içerir ve ContactsContract.Data şemasını izler.
// Data class representing a parsed Contact with selected details.
data class Contact(
val lookupKey: String,
val name: String,
val emails: List<String>,
val phones: List<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.LOOKUP_KEY,
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)
)
// We use `LOOKUP_KEY` as a unique ID to aggregate all contact info related to a same person
val contactsMap = mutableMapOf<String, Contact>()
// Note: The Contact Picker Session Uri doesn't support custom selection & selectionArgs.
// We query the URI directly to get the results chosen by the user.
context.contentResolver.query(sessionUri, projection, null, null, null)?.use { cursor ->
// Get the column indices for our requested projection
val lookupKeyIdx = cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)
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 lookupKey = cursor.getString(lookupKeyIdx)
val mimeType = cursor.getString(mimeTypeIdx)
val name = cursor.getString(nameIdx) ?: ""
val data1 = cursor.getString(data1Idx) ?: ""
val email = if (mimeType == Email.CONTENT_ITEM_TYPE) data1 else null
val phone = if (mimeType == Phone.CONTENT_ITEM_TYPE) data1 else null
val existingContact = contactsMap[lookupKey]
if (existingContact != null) {
contactsMap[lookupKey] = existingContact.copy(
emails = if (email != null) existingContact.emails + email else existingContact.emails,
phones = if (phone != null) existingContact.phones + phone else existingContact.phones
)
} else {
contactsMap[lookupKey] = Contact(
lookupKey = lookupKey,
name = name,
emails = if (email != null) listOf(email) else emptyList(),
phones = if (phone != null) listOf(phone) else emptyList()
)
}
}
}
return@withContext contactsMap.values.toList()
}
Geriye Dönük Uyumluluk
Android 17 (API düzeyi 37) ve sonraki sürümleri hedefleyen uygulamalarda sistem, mevcut Intent.ACTION_PICK amacını otomatik olarak yeni Kişi Seçici arayüzünü kullanacak şekilde yükseltir.
Uygulamanızda zaten ACTION_PICK kullanılıyorsa yeni kullanıcı arayüzünü almak için kodunuzu değiştirmeniz gerekmez. Ancak, tek bir Uri ile iletişim verilerini sorgulama, kişisel ve iş profilleri arasında geçiş yapma veya birden fazla veri alanı isteği gibi yeni özelliklerden yararlanmak için uygulamanızı Intent.ACTION_PICK_CONTACTS veya yeni amaç ekstralarını kullanacak şekilde güncellemeniz gerekir.
Eski hedef SDK'larda test etme
Uygulamanız daha düşük bir SDK sürümünü hedeflese bile EXTRA_USE_SYSTEM_CONTACTS_PICKER boolean ekstrasını ACTION_PICK amacınıza ekleyerek Android 17 ve sonraki sürümlerin yüklü olduğu cihazlarda yeni seçici davranışını test edebilirsiniz.
En iyi uygulamalar
- Yalnızca ihtiyacınız olanı isteyin: Uygulamanızın yalnızca SMS göndermesi gerekiyorsa
Phone.CONTENT_ITEM_TYPEiznini isteyin. Seçici, telefon numarası olmayan kişileri otomatik olarak filtreleyerek kullanıcı için daha temiz bir kullanıcı arayüzü sağlar. - Kişi başına birden fazla veri girişini yönetme: Kişiler genellikle çeşitli e-posta adresleri veya telefon numaraları içerir. Bunların kullanıcıya net ve sezgisel bir şekilde sunulmasını sağlamak için
ContactsContract.Contacts.LOOKUP_KEYkullanarak gruplandırmanız önerilir. Ayrıca, uygulamanızın arayüzünde daha ayrıntılı seçim seçenekleri sunmak için her girişle ilgili belirli etiketleri (ör. iş veya kişisel) alabilirsiniz. - Verileri hemen kalıcı hale getirme: Oturum URI'si geçici okuma izni verir. Bu iletişim bilgilerine daha sonra (uygulama işleminiz sonlandırıldıktan sonra) erişmeniz gerekirse uygulamanızın iletişim verilerini kalıcı olarak saklaması gerekir.
- Hesap verilerine güvenmeyin: Kullanıcı gizliliğini korumak ve parmak izi oluşturmayı önlemek için sonuçlardan hesaba özel meta veriler kaldırılır.