Android कॉन्टैक्ट पिकर, एक स्टैंडर्ड इंटरफ़ेस है. इसकी मदद से, उपयोगकर्ता आपके ऐप्लिकेशन के साथ संपर्क शेयर कर सकते हैं. यह इंटरफ़ेस, Android 17 (एपीआई लेवल 37) या इसके बाद के वर्शन वाले डिवाइसों पर उपलब्ध है. पिकर, READ_CONTACTS अनुमति के विकल्प के तौर पर काम करता है. इससे उपयोगकर्ता की निजता बनी रहती है. आपका ऐप्लिकेशन, उपयोगकर्ता की पूरी पता पुस्तिका को ऐक्सेस करने का अनुरोध करने के बजाय, उन डेटा फ़ील्ड के बारे में बताता है जिनकी उसे ज़रूरत है. जैसे, फ़ोन नंबर या ईमेल पते. इसके बाद, उपयोगकर्ता शेयर करने के लिए खास संपर्क चुनता है. इससे, आपके ऐप्लिकेशन को सिर्फ़ चुने गए डेटा को पढ़ने की अनुमति मिलती है. साथ ही, यह पक्का किया जाता है कि डेटा पर पूरी तरह से कंट्रोल किया जा सके. इसके अलावा, इसमें खोज, प्रोफ़ाइल स्विच करने, और एक साथ कई विकल्प चुनने की सुविधाएं भी शामिल हैं. इससे, यूज़र इंटरफ़ेस (यूआई) बनाने या उसे बनाए रखने की ज़रूरत नहीं पड़ती.
कॉन्टैक्ट पिकर को इंटिग्रेट करना
कॉन्टैक्ट पिकर को इंटिग्रेट करने के लिए, Intent.ACTION_PICK_CONTACTS इंटेंट का इस्तेमाल करें.
इस इंटेंट से पिकर लॉन्च होता है और चुने गए संपर्क आपके ऐप्लिकेशन पर दिखते हैं.
पुराने ACTION_PICK के उलट, कॉन्टैक्ट पिकर की मदद से, एक ही समय में कई डेटा फ़ील्ड तय किए जा सकते हैं. इसके लिए,
Intent.EXTRA_REQUESTED_DATA_FIELDS का इस्तेमाल करें. साथ ही, MIME
टाइप की ArrayList<String> पास करें, जो ContactsContract.CommonDataKinds में तय किए गए हैं.
सामान्य MIME टाइप में ये शामिल हैं:
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPEContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPEContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE
पिकर लॉन्च करना
पिकर लॉन्च करने के लिए, StartActivityForResult कॉन्ट्रैक्ट के साथ registerForActivityResult का इस्तेमाल करें. इंटेंट को इस तरह कॉन्फ़िगर किया जा सकता है कि एक या एक से ज़्यादा विकल्प चुने जा सकें.
// 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)
}
}
}
चुनने का मोड
कॉन्टैक्ट पिकर का यूज़र इंटरफ़ेस (यूआई), अनुरोध किए गए डेटा फ़ील्ड के हिसाब से बदलता है. इन ज़रूरी शर्तों के आधार पर, उपयोगकर्ता कई फ़ील्ड की ज़रूरत होने पर, पूरे संपर्क रिकॉर्ड को चुन सकते हैं. इसके अलावा, वे किसी संपर्क की जानकारी में से खास डेटा आइटम भी चुन सकते हैं.
कोई एक संपर्क चुनना
इस उदाहरण में, ऐप्लिकेशन सिर्फ़ फ़ोन नंबर का अनुरोध करता है. पिकर, सूची को फ़िल्टर करके सिर्फ़ फ़ोन नंबर वाले संपर्क दिखाएगा. साथ ही, उपयोगकर्ता को कोई खास नंबर चुनने की अनुमति देगा.
// 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)
एक से ज़्यादा संपर्क चुनना
एक से ज़्यादा विकल्प चुनने की सुविधा चालू करने के लिए, Intent.EXTRA_ALLOW_MULTIPLE एक्स्ट्रा जोड़ें. आपके पास यह तय करने का विकल्प होता है कि कोई उपयोगकर्ता कितने आइटम चुन सकता है.
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)
नतीजों को मैनेज करना
जब उपयोगकर्ता विकल्प चुन लेता है, तो सिस्टम RESULT_OK और सेशन यूआरआई दिखाता है. इस यूआरआई से, चुने गए डेटा को पढ़ने की अस्थायी अनुमति मिलती है.
ContentResolver के स्टैंडर्ड का इस्तेमाल करके, इस यूआरआई के लिए क्वेरी की जा सकती है. इससे मिलने वाले Cursor में, अनुरोध किए गए डेटा फ़ील्ड शामिल होते हैं. साथ ही, यह ContactsContract.Data के स्कीमा के मुताबिक होता है.
// 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()
}
पुराने सिस्टम के साथ काम करने की सुविधा
Android 17 (एपीआई लेवल 37) और इसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन के लिए, सिस्टम मौजूदा Intent.ACTION_PICK इंटेंट को अपने-आप अपग्रेड कर देता है, ताकि नए कॉन्टैक्ट पिकर इंटरफ़ेस का इस्तेमाल किया जा सके.
अगर आपका ऐप्लिकेशन पहले से ही ACTION_PICK का इस्तेमाल करता है, तो आपको नया यूज़र इंटरफ़ेस (यूआई) पाने के लिए, अपने कोड में बदलाव करने की ज़रूरत नहीं है. हालांकि, नई सुविधाओं का फ़ायदा पाने के लिए, आपको अपने कोड को अपडेट करना होगा. जैसे, संपर्क डेटा के लिए क्वेरी करने के लिए एक Uri पाना, निजी और ऑफ़िस की प्रोफ़ाइल के बीच स्विच करना या कई डेटा फ़ील्ड के लिए अनुरोध करना. इसके लिए, आपको Intent.ACTION_PICK_CONTACTS या नए इंटेंट एक्स्ट्रा का इस्तेमाल करना होगा.
पुराने टारगेट एसडीके पर जांच करना
ACTION_PICK इंटेंट में, EXTRA_USE_SYSTEM_CONTACTS_PICKER बूलियन एक्स्ट्रा जोड़कर, Android 17 और इसके बाद के वर्शन वाले डिवाइसों पर, नए पिकर के व्यवहार की जांच की जा सकती है. भले ही, आपका ऐप्लिकेशन एसडीके के पुराने वर्शन को टारगेट करता हो.
सबसे सही तरीके
- सिर्फ़ ज़रूरी जानकारी का अनुरोध करें: अगर आपके ऐप्लिकेशन को सिर्फ़ एसएमएस भेजना है,
तो
Phone.CONTENT_ITEM_TYPEका अनुरोध करें. पिकर, उन संपर्कों को अपने-आप फ़िल्टर कर देगा जिनके पास फ़ोन नंबर नहीं हैं. इससे, उपयोगकर्ता के लिए यूज़र इंटरफ़ेस (यूआई) साफ़ दिखेगा. - हर संपर्क के लिए कई डेटा एंट्री मैनेज करना: अक्सर, अलग-अलग संपर्कों में कई ईमेल पते या फ़ोन नंबर होते हैं. यह पक्का करने के लिए कि उपयोगकर्ताओं को ये साफ़ तौर पर और आसानी से दिखें, इन्हें
ContactsContract.Contacts.LOOKUP_KEYका इस्तेमाल करके ग्रुप करने का सुझाव दिया जाता है. इसके अलावा, आपके पास हर एंट्री के लिए खास लेबल (जैसे, ऑफ़िस या निजी) पाने का विकल्प होता है, ताकि आपके ऐप्लिकेशन के इंटरफ़ेस में ज़्यादा विकल्प दिए जा सकें. - डेटा को तुरंत सेव करें: सेशन यूआरआई से, डेटा को पढ़ने की अस्थायी अनुमति मिलती है. अगर आपको बाद में (आपके ऐप्लिकेशन की प्रोसेस बंद होने के बाद) इस संपर्क जानकारी को ऐक्सेस करना है, तो आपके ऐप्लिकेशन को संपर्क डेटा सेव करना होगा.
- खाते के डेटा पर भरोसा न करें: उपयोगकर्ता की निजता को सुरक्षित रखने और फ़िंगरप्रिंटिंग से बचाने के लिए, नतीजों से खाते के लिए खास मेटाडेटा हटा दिया जाता है.