Ürün Haberleri

Kişi Seçici: Gizlilik Öncelikli Kişi Paylaşımı

Okuma süresi: 4 dk.
Roxanna Aliabadi Walker'ın profilini görüntüle
Roxanna Aliabadi Walker Ürün Müdürü, Android

Gizlilik ve kullanıcı kontrolü, Android deneyiminin merkezinde yer almaya devam ediyor. Fotoğraf seçici, medya paylaşımını güvenli ve kolay hale getirdi. Şimdi aynı düzeyde gizlilik, basitlik ve mükemmel kullanıcı deneyimini kişi seçimine de getiriyoruz.

İletişim Gizliliği İçin Yeni Bir Standart

Geçmişte, belirli bir kullanıcının kişilerine erişim gerektiren uygulamalar geniş kapsamlı READ_CONTACTS iznini kullanıyordu. Bu yaklaşım işlevsel olsa da genellikle uygulamalara gerekenden daha fazla veri erişimi veriyordu. Android 17'de kullanıma sunulan yeni Android Kişi Seçici, kişi seçimi için standartlaştırılmış, güvenli ve aranabilir bir arayüz sağlayarak bu dinamiği değiştirir.

Bu özellik, kullanıcıların uygulamalara yalnızca seçtikleri kişilere erişim izni vermesini sağlayarak Android'in veri şeffaflığı ve izin ayak izlerini en aza indirme taahhüdüyle uyumludur.

picker.png
selection.png

İşleyiş Şekli

Geliştiriciler, Intent.ACTION_PICK_CONTACTS intent'ini kullanarak Kişi Seçici'yi entegre edebilir. Bu güncellenmiş API, çeşitli güçlü özellikler sunar:

  • Ayrıntılı veri istekleri: Uygulamalar, kişi kaydının tamamını almak yerine tam olarak ihtiyaç duydukları alanları (ör. telefon numaraları veya e-posta adresleri) belirtebilir.
  • Çoklu seçim desteği: Seçici, hem tek hem de birden fazla kişi seçimini destekleyerek geliştiricilere grup davetiyeleri gibi özellikler için daha fazla esneklik sağlar.
  • Seçim sınırları: Geliştiriciler, kullanıcıların tek seferde seçebileceği kişi sayısına özel sınırlar belirleyebilir.
  • Geçici Erişim: Bu seçenek belirlendiğinde sistem, istenen verilere geçici okuma erişimi sağlayan bir oturum URI'si döndürür. Böylece erişimin gerektiğinden daha uzun süre devam etmemesi sağlanır.
  • Diğer profillere erişim: Bu yeni intent kullanıldığında arayüz, kullanıcıların iş profili, klonlanmış profil veya özel alan gibi diğer kullanıcı profillerinden içerik seçmesine olanak tanır.
  • Optimize edilmiş performans: Kişi seçici, toplu sonuç sorgulamaya olanak tanıyan tek bir URI döndürür. Böylece, ACTION_PICK tarafından gerekli kılındığı şekilde her bir kişi URI'sini ayrı ayrı sorgulama ihtiyacı ortadan kalkar. Bu verimlilik, tek bir Binder işlemi kullanarak sistem ek yükünü daha da azaltır.

Geriye dönük uyumluluk ve uygulama

Android 17 veya sonraki sürümleri çalıştıran cihazlarda sistem, kişi veri türlerini belirten eski ACTION_PICK intent'lerini otomatik olarak yeni ve daha güvenli arayüze yükseltir. Ancak çoklu seçim gibi ileri seviye özelliklerden tam olarak yararlanmak için geliştiricilerin uygulama kodlarını güncellemeleri ve döndürülen oturum URI'sini sorgulamak için ContentResolver kullanmaları önerilir.


Kişi seçiciyi entegre etmeGeliştiriciler, kişi seçiciyi entegre etmek için ACTION_PICK_CONTACTS intent'ini kullanır. Aşağıda, seçiciyi nasıl başlatacağınızı ve e-posta ile telefon numaraları gibi belirli veri alanlarını nasıl isteyeceğinizi gösteren bir kod örneği verilmiştir.

// 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)

Kullanıcı seçim yaptıktan sonra uygulama, istenen iletişim bilgilerini ayıklamak için döndürülen oturum URI'sini sorgulayarak sonucu işler.

// 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
}

Belgelerin tamamını buradan inceleyebilirsiniz.

Geliştiriciler için En İyi Uygulamalar

En iyi kullanıcı deneyimini sunmak ve yüksek güvenlik standartlarını korumak için aşağıdakileri yapmanızı öneririz:

  • Minimum Veri (Toplama): Yalnızca uygulamanızın ihtiyaç duyduğu belirli veri alanlarını (ör. e-posta) isteyin.
  • Anında kalıcılık: Oturum URI'si erişimi geçici olduğundan seçili verileri hemen kalıcı hale getirin.
Okumaya devam et