منتقي جهات الاتصال: مشاركة جهات الاتصال مع التركيز على الخصوصية
مدّة القراءة: 4 دقائق
تظل الخصوصية وتحكّم المستخدم في صميم تجربة Android. تمامًا كما جعلت "أداة اختيار الصور" مشاركة الوسائط آمنة وسهلة التنفيذ، نقدّم الآن المستوى نفسه من الخصوصية والبساطة وتجربة المستخدم الرائعة لاختيار جهات الاتصال.
معيار جديد لخصوصية جهات الاتصال
في السابق، كانت التطبيقات التي تتطلّب الوصول إلى جهات اتصال مستخدم معيّن تعتمد على إذن READ_CONTACTS الواسع النطاق. وعلى الرغم من أنّ هذا الأسلوب كان عمليًا، فإنّه غالبًا ما كان يمنح التطبيقات إمكانية الوصول إلى بيانات أكثر من اللازم. يغيّر "منتقي جهات الاتصال في Android" الجديد، الذي تم طرحه في الإصدار 17 من نظام التشغيل Android، هذه الآلية من خلال توفير واجهة موحّدة وآمنة وقابلة للبحث لاختيار جهات الاتصال.
تتيح هذه الميزة للمستخدمين منح التطبيقات إذن الوصول إلى جهات الاتصال المحدّدة التي يختارونها فقط، بما يتوافق مع التزام Android بشفافية البيانات وتقليل أذونات الوصول إلى البيانات.
كيفية العمل
يمكن للمطوّرين دمج "منتقي جهات الاتصال" باستخدام الغرض Intent.ACTION_PICK_CONTACTS . توفّر واجهة برمجة التطبيقات المعدَّلة هذه العديد من الإمكانات الفعّالة:
- طلبات البيانات الدقيقة: يمكن للتطبيقات تحديد الحقول التي تحتاج إليها بالضبط، مثل أرقام الهواتف أو عناوين البريد الإلكتروني، بدلاً من تلقّي سجلّ جهة الاتصال بالكامل.
- إتاحة الاختيار المتعدّد: تتيح أداة الاختيار اختيار جهة اتصال واحدة أو جهات اتصال متعدّدة، ما يمنح المطوّرين مرونة أكبر في ميزات مثل الدعوات الجماعية.
- حدود الاختيار: يمكن للمطوّرين وضع حدود مخصّصة لعدد جهات الاتصال التي يمكن للمستخدم اختيارها في المرة الواحدة.
- الوصول المؤقت: عند اختيار هذا الإعداد، يعرض النظام معرّف موارد منتظم (URI) للجلسة يوفّر إذن وصول مؤقتًا للقراءة إلى البيانات المطلوبة، ما يضمن عدم استمرار الوصول لفترة أطول من اللازم.
- الوصول إلى ملفات المستخدم الشخصية الأخرى: عند استخدام هذا الغرض الجديد، ستسمح الواجهة للمستخدمين باختيار محتوى من ملفات المستخدم الشخصية الأخرى، مثل ملف العمل أو ملف المستخدم الشخصي المستنسَخ أو المساحة الخاصّة.
- تحسين الأداء: يعرض منتقي جهات الاتصال معرّف موارد منتظم (URI) واحدًا يتيح الاستعلام عن النتائج بشكل جماعي، ما يلغي الحاجة إلى الاستعلام عن معرّف الموارد المنتظم (URI) لكل جهة اتصال على حدة كما هو مطلوب في
ACTION_PICK. وتؤدي هذه الكفاءة إلى تقليل عبء النظام من خلال استخدام معاملةBinderواحدة.
التوافق مع الأنظمة القديمة والتنفيذ
بالنسبة إلى الأجهزة التي تعمل بالإصدار 17 من نظام التشغيل Android أو الإصدارات الأحدث، يرقّي النظام تلقائيًا الأغراض القديمة 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) للجلسة يكون مؤقتًا.
-
أخبار المنتجاتلن تتمكّن التطبيقات التي تستهدف إصدار Android القادم من تعديل جهات الاتصال مباشرةً باستخدام إذن WRITE_CONTACTS.
Roxanna Aliabadi Walker • مدّة القراءة: 6 دقائق -
أخبار المنتجات"أداة اختيار الصور" المضمّنة: طريقة أكثر سلاسة لطلب الصور والفيديوهات بشكل خاص في تطبيقك
Roxanna Aliabadi Walker, Yacine Rezgui • مدّة القراءة: 8 دقائق -
أخبار المنتجاتبما أنّ Unity تشغّل أكثر من نصف جميع الألعاب على الأجهزة الجوّالة في جميع أنحاء العالم، فإنّ الانطباعات الأولى مهمة. بالنسبة إلى مطوّري الألعاب، تُعدّ تجربة الإعداد السلسة والموثوقة للاعبين ضرورية لتعزيز معدّل الاحتفاظ باللاعبين من اليوم الأول وزيادة تفاعلهم على المدى الطويل.
Michelle Martin • مدّة القراءة: دقيقة واحدة
يمكنك الحصول على آخر الإحصاءات حول تطوير تطبيقات Android في بريدك الوارد أسبوعيًا.