Android পরিচিতি পিকার হল একটি স্ট্যান্ডার্ড, ব্রাউজ করা যায় এমন ইন্টারফেস যার মাধ্যমে ব্যবহারকারীরা
আপনার অ্যাপের সাথে পরিচিতি শেয়ার করতে পারেন। Android 17 (API লেভেল ৩৭) বা তার পরবর্তী যেকোনও ভার্সন
চালানো ডিভাইসে উপলভ্য, পিকারটি READ_CONTACTS অনুমতির একটি গোপনীয়তা-সংরক্ষণকারী
বিকল্প অফার করে। ব্যবহারকারীর সম্পূর্ণ অ্যাড্রেস বুক অ্যাক্সেস করার অনুরোধ করার পরিবর্তে, আপনার অ্যাপ ফোন নম্বর বা ইমেল আইডির মতো প্রয়োজনীয় ডেটা ফিল্ড নির্দিষ্ট করে এবং ব্যবহারকারী শেয়ার করার জন্য নির্দিষ্ট পরিচিতি বেছে নেন। এটি আপনার অ্যাপকে শুধুমাত্র বেছে নেওয়া ডেটা পড়ার অ্যাক্সেস দেয়,
বিল্ট-ইন সার্চ, প্রোফাইল পাল্টানো এবং UI তৈরি বা ম্যানেজ না করেই
একাধিক আইটেম বেছে নেওয়ার ক্ষমতা সহ ব্যবহারকারীকে ধারাবাহিক অভিজ্ঞতা প্রদান করার সময়
গ্র্যানুলার কন্ট্রোল নিশ্চিত করে।
পরিচিতি পিকার ইন্টিগ্রেট করা
পরিচিতি পিকার ইন্টিগ্রেট করতে, ContactsPickerSessionContract.ACTION_PICK_CONTACTS ইনটেন্ট ব্যবহার করুন।
এই ইনটেন্ট পিকার চালু করে এবং বেছে নেওয়া পরিচিতি আপনার অ্যাপে ফিরিয়ে দেয়।
পুরনো ACTION_PICK-এর মতো নয়, পরিচিতি পিকার আপনাকে একই সময়ে আপনার অ্যাপের জন্য প্রয়োজনীয় একাধিক
ডেটা ফিল্ড নির্দিষ্ট করতে দেয়। আপনি
ContactsPickerSessionContract.EXTRA_REQUESTED_DATA_FIELDS ব্যবহার করে এটি করেন, ContactsContract.CommonDataKinds-এ সংজ্ঞায়িত MIME প্রকারের
ArrayList<String> পাস করেন।
সাধারণ 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)
}
}
}
বেছে নেওয়ার মোড
অনুরোধ করা ডেটা ফিল্ড অনুযায়ী পরিচিতি পিকারের UI অ্যাডজাস্ট হয়। এইসব প্রয়োজনীয়তার উপর নির্ভর করে, ব্যবহারকারী একাধিক ফিল্ডের প্রয়োজন হলে, সম্পূর্ণ পরিচিতি রেকর্ড বেছে নিতে পারেন অথবা পরিচিতির তথ্যের মধ্যে থেকে নির্দিষ্ট ডেটা আইটেম বেছে নিতে পারেন।
একটি পরিচিতি বেছে নিন
এই উদাহরণে, অ্যাপটি শুধুমাত্র ফোন নম্বর চায়। পিকার তালিকা ফিল্টার করে শুধু ফোন নম্বর সহ পরিচিতি দেখাবে এবং ব্যবহারকারীকে নির্দিষ্ট নম্বর বেছে নিতে দেবে।
// 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_USE_SYSTEM_CONTACTS_PICKER, true)
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 {
putExtra(EXTRA_USE_SYSTEM_CONTACTS_PICKER, true)
// 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 এবং
সেশন URI রিটার্ন করে। এই URI বেছে নেওয়া ডেটা সাময়িকভাবে পড়ার অ্যাক্সেস দেয়।
আপনি স্ট্যান্ডার্ড ContentResolver ব্যবহার করে এই URI কোয়েরি করতে পারবেন। ফলাফল হিসেবে পাওয়া
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 (API লেভেল 37) এবং তার পরবর্তী ভার্সনকে টার্গেট করা অ্যাপের জন্য, সিস্টেম
নতুন পরিচিতি পিকার ইন্টারফেস ব্যবহার করার জন্য আগে থেকে থাকা Intent.ACTION_PICK ইনটেন্টকে
অটোমেটিক আপগ্রেড করে।
আপনার অ্যাপে আগে থেকেই ACTION_PICK ব্যবহার করা হলে, নতুন UI পেতে
আপনাকে কোড পরিবর্তন করতে হবে না। তবে, নতুন ফিচারের সুবিধা নিতে, যেমন
পরিচিতির ডেটা কোয়েরি করার জন্য একটি Uri পাওয়া, ব্যক্তিগত ও
অফিস প্রোফাইল বা একাধিক ডেটা ফিল্ডের অনুরোধের মধ্যে পরিবর্তন করা, আপনাকে
ContactsPickerSessionContract.ACTION_PICK_CONTACTS বা
নতুন ইনটেন্ট এক্সট্রা ব্যবহার করার জন্য আপনার ইমপ্লিমেন্টেশন আপডেট করতে হবে।
পুরনো টার্গেট SDK-তে পরীক্ষা করা
আপনার অ্যাপ যদি কম SDK ভার্সনকে টার্গেট করে, তাহলেও আপনি Android 17 এবং
তার পরবর্তী ভার্সনে চলা ডিভাইসে নতুন পিকারের আচরণ পরীক্ষা করতে পারেন। এর জন্য আপনার ACTION_PICK ইনটেন্টে
EXTRA_USE_SYSTEM_CONTACTS_PICKER বুলিয়ান এক্সট্রা যোগ করতে হবে।
পেশাদার পদ্ধতি
- শুধু যা প্রয়োজন তার জন্য অনুরোধ করুন: আপনার অ্যাপের শুধু এসএমএস পাঠানোর প্রয়োজন হলে,
Phone.CONTENT_ITEM_TYPE-এর জন্য অনুরোধ করুন। পিকার অটোমেটিক সেইসব পরিচিতি ফিল্টার করে দেবে যেগুলির ফোন নম্বর নেই, এর ফলে ব্যবহারকারী আরও পরিষ্কার UI দেখতে পাবেন। - প্রতিটি পরিচিতির জন্য একাধিক ডেটা এন্ট্রি ম্যানেজ করা: প্রতিটি পরিচিতিতে প্রায়ই
বিভিন্ন ইমেল আইডি বা ফোন নম্বর থাকে। ব্যবহারকারীর কাছে এগুলি যাতে স্পষ্ট ও সহজভাবে
উপস্থাপিত হয় তা নিশ্চিত করতে,
ContactsContract.Contacts.LOOKUP_KEYব্যবহার করে এগুলি গ্রুপে রাখলে ভালো হয়। এছাড়াও, আপনি প্রতিটি এন্ট্রির জন্য নির্দিষ্ট লেবেল (যেমন অফিস বা ব্যক্তিগত) ফিরিয়ে আনতে পারবেন যাতে আপনার অ্যাপের ইন্টারফেসে আরও সূক্ষ্মভাবে বেছে নেওয়ার বিকল্প অফার করা যায়। - ডেটা অবিলম্বে পারসিস্ট করুন: সেশন URI সাময়িক রিড পার্মিশন প্রদান করে। আপনাকে যদি পরে এই পরিচিতির তথ্য অ্যাক্সেস করতে হয় (আপনার অ্যাপ প্রসেস বন্ধ হয়ে যাওয়ার পরে), তাহলে আপনার অ্যাপকে পরিচিতির ডেটা সেভ করে রাখতে হবে।
- অ্যাকাউন্ট ডেটার উপর নির্ভর করবেন না: ব্যবহারকারীর গোপনীয়তা রক্ষা করতে এবং ফিঙ্গারপ্রিন্টিং আটকাতে, ফলাফল থেকে অ্যাকাউন্ট-নির্দিষ্ট মেটাডেটা সরিয়ে দেওয়া হয়।