חדשות על המוצר

הכלי לבחירת אנשי קשר: שיתוף אנשי קשר מוכוון פרטיות

משך הקריאה: 4 דקות
לצפייה בפרופיל של רוקסנה אליאבדי ווקר
Roxanna Aliabadi Walker מנהל מוצר, Android

הפרטיות והשליטה של המשתמשים עדיין נמצאות בלב חוויית השימוש ב-Android. כמו שהכלי לבחירת תמונות הפך את שיתוף המדיה למאובטח וקל ליישום, עכשיו אנחנו מביאים את אותה רמה של פרטיות, פשטות וחוויית משתמש מעולה לבחירת אנשי קשר.

סטנדרט חדש לפרטיות של אנשי הקשר

בעבר, אפליקציות שדרשו גישה לאנשי הקשר של משתמש מסוים הסתמכו על ההרשאה הרחבה READ_CONTACTS. הגישה הזו אמנם הייתה פונקציונלית, אבל לעיתים קרובות היא העניקה לאפליקציות גישה ליותר נתונים מהנדרש. הכלי החדש לבחירת אנשי קשר ב-Android, שהושק ב-Android 17, משנה את הדינמיקה הזו ומספק ממשק סטנדרטי, מאובטח וניתן לחיפוש לבחירת אנשי קשר.

התכונה הזו מאפשרת למשתמשים לתת לאפליקציות גישה רק לאנשי הקשר הספציפיים שהם בוחרים, בהתאם למחויבות של Android לשקיפות נתונים ולצמצום טביעת הרגל של ההרשאות.

picker.png
selection.png

איך זה עובד

מפתחים יכולים לשלב את הכלי לבחירת אנשי קשר באמצעות ה-intent Intent.ACTION_PICK_CONTACTS. ה-API המעודכן הזה מציע כמה יכולות מתקדמות:

  • בקשות לנתונים ספציפיים: אפליקציות יכולות לציין בדיוק אילו שדות הן צריכות, כמו מספרי טלפון או כתובות אימייל, במקום לקבל את כל הרשומה של איש הקשר.
  • תמיכה בבחירה מרובה: הכלי לבחירת אנשי קשר תומך בבחירה של איש קשר אחד או כמה אנשי קשר, וכך מאפשר למפתחים גמישות רבה יותר בתכונות כמו הזמנות קבוצתיות.
  • מגבלות בחירה: המפתחים יכולים להגדיר מגבלות מותאמות אישית על מספר אנשי הקשר שמשתמש יכול לבחור בבת אחת.
  • גישה זמנית: אחרי הבחירה, המערכת מחזירה URI של סשן שמספק גישה זמנית לקריאה של הנתונים המבוקשים, כדי לוודא שהגישה לא נמשכת יותר מהנדרש.
  • גישה לפרופילים אחרים: כשמשתמשים ב-Intent החדש הזה, הממשק מאפשר למשתמשים לבחור תוכן מפרופילים אחרים, כמו פרופיל עבודה, פרופיל משוכפל או מרחב פרטי.
  • ביצועים אופטימליים:  הכלי לבחירת אנשי קשר מחזיר URI יחיד שמאפשר לשלוח שאילתות על תוצאות קולקטיביות, וכך אין צורך לשלוח שאילתות על URI של אנשי קשר נפרדים בנפרד, כפי שנדרש על ידי ACTION_PICK. היעילות הזו מפחיתה עוד יותר את התקורה של המערכת באמצעות טרנזקציה אחת של Binder.

תאימות לדורות קודמים והטמעה

במכשירים עם Android בגרסה 17 ואילך, המערכת משדרגת באופן אוטומטי את ה-Intent הקודמים של ACTION_PICK שמציינים סוגים של נתוני אנשי קשר לממשק החדש והמאובטח יותר. עם זאת, כדי לנצל את כל היתרונות של תכונות מתקדמות כמו בחירה מרובה, מומלץ למפתחים לעדכן את קוד ההטמעה ולהשתמש ב-ContentResolver כדי לשלוח שאילתה ל-URI של הסשן שהוחזר.


שילוב הכלי לבחירת אנשי קשרכדי לשלב את הכלי לבחירת אנשי קשר, המפתחים משתמשים ב-Intent 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 של הסשן היא זמנית.
כותב/ת המסמך:
להמשך קריאה