اخبار محصول

انتخابگر مخاطب: هم‌رسانی مخاطب با اولویت حریم خصوصی

زمان خواندن: ۴ دقیقه
مشاهده نمایه Roxanna Aliabadi Walker
Roxanna Aliabadi Walker مدیر محصول، Android

حریم خصوصی و کنترل کاربر همچنان در کانون تجربه Android قرار دارد. همان‌طور که انتخاب‌گر عکس هم‌رسانی رسانه را ایمن و پیاده‌سازی آن را آسان کرد، اکنون همان سطح از حریم خصوصی، سادگی، و تجربه کاربری عالی را به انتخاب مخاطب می‌آوریم.

استانداردی جدید برای حریم خصوصی مخاطب

در گذشته، برنامه‌هایی که به دسترسی به مخاطبین کاربر خاصی نیاز داشتند به اجازه گسترده READ_CONTACTS متکی بودند. هرچند این رویکرد کاربردی بود، اما اغلب داده‌های بیشتری از حد نیاز به برنامه‌ها اعطا می‌کرد. «انتخابگر مخاطب Android» جدید که در Android 17 معرفی شده است، این پویایی را با ارائه یک میانای استاندارد، امن، و قابل‌جستجو برای انتخاب مخاطب تغییر می‌دهد.

این ویژگی به کاربران امکان می‌دهد فقط به مخاطبین خاصی که انتخاب می‌کنند دسترسی به برنامه‌ها را اعطا کنند، که با تعهد Android به شفافیت داده‌ها و به‌حداقل رساندن ردپای اجازه‌ها همسو است.

picker.png
selection.png

روش کار

توسعه‌دهندگان می‌توانند بااستفاده از هدف Intent.ACTION_PICK_CONTACTS «انتخابگر مخاطب» را ادغام کنند. این میانای برنامه‌سازی کاربردی به‌روزشده چندین قابلیت قدرتمند ارائه می‌دهد:

  • درخواست‌های داده‌های جزئی: برنامه‌ها می‌توانند دقیقاً مشخص کنند به کدام فیلدها نیاز دارند، مثلاً شماره تلفن یا نشانی ایمیل، به‌جای اینکه کل سابقه مخاطب را دریافت کنند.
  • پشتیبانی از چندانتخابی: این انتخابگر از انتخاب یک یا چند مخاطب پشتیبانی می‌کند و به توسعه‌دهندگان انعطاف‌پذیری بیشتری برای ویژگی‌هایی مانند دعوت‌های گروهی می‌دهد.
  • محدودیت‌های انتخاب: توسعه‌دهندگان می‌توانند محدودیت‌های سفارشی برای تعداد مخاطبینی که کاربر می‌تواند به‌طور هم‌زمان انتخاب کند تنظیم کنند.
  • دسترسی موقت: پس‌از انتخاب، سیستم یک 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)

پس‌از اینکه کاربر انتخاب کرد، برنامه با جستجو کردن «شناسه منبع یکسان» جلسه برگردانده‌شده، نتیجه را پردازش می‌کند تا اطلاعات تماس درخواست‌شده را استخراج کند.

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

مستندات کامل را در اینجا بررسی کنید.

روال‌های مطلوب برای توسعه‌دهندگان

برای ارائه بهترین تجربه کاربری و حفظ استانداردهای امنیتی بالا، موارد زیر را توصیه می‌کنیم:

  • کمینه‌سازی جمع‌آوری داده: فقط فیلدهای داده خاصی (مثل ایمیل) را که برنامه‌تان نیاز دارد درخواست کنید.
  • ماندگاری فوری: داده‌های انتخاب‌شده را فوراً ماندگار کنید، زیرا دسترسی به شناسه منبع یکسان جلسه موقتی است.
ادامه خواندن