इस लेसन में, उन संपर्कों की सूची पाने का तरीका बताया गया है जिनका डेटा, खोज स्ट्रिंग के पूरे या कुछ हिस्से से मैच करता है. इसके लिए, इन तकनीकों का इस्तेमाल किया जाता है:
- संपर्कों के नाम मैच करना
- खोज स्ट्रिंग को संपर्क के नाम के डेटा के पूरे या कुछ हिस्से से मैच करके, संपर्कों की सूची पाएं. संपर्क सेवा देने वाली कंपनी, एक ही नाम को कई बार इस्तेमाल करने की अनुमति देती है. इससे, यह तकनीक मिलानों की सूची दिखा सकती है.
- किसी खास तरह के डेटा से मैच करना, जैसे कि फ़ोन नंबर
- खोज स्ट्रिंग को खास तरह की जानकारी वाले डेटा, जैसे कि ईमेल पते से मैच करके, संपर्कों की सूची वापस पाई जा सकती है. उदाहरण के लिए, इस तकनीक से उन सभी संपर्कों की सूची बनाई जा सकती है जिनके ईमेल पते, खोज स्ट्रिंग से मेल खाते हैं.
- किसी भी तरह के डेटा से मैच करना
- खोज स्ट्रिंग को किसी भी तरह की ज़्यादा जानकारी वाले डेटा से मैच करके, संपर्कों की सूची वापस पाएं. इसमें नाम, फ़ोन नंबर, मोहल्ले का पता, ईमेल पता वगैरह शामिल हैं. उदाहरण के लिए, इस तकनीक की मदद से, खोज स्ट्रिंग के लिए किसी भी तरह का डेटा स्वीकार किया जा सकता है. इसके बाद, उन संपर्कों की सूची बनाई जा सकती है जिनका डेटा स्ट्रिंग से मेल खाता है.
ध्यान दें: इस लेसन के सभी उदाहरणों में, संपर्क सूची की सेवा देने वाली कंपनी से डेटा पाने के लिए,
CursorLoader
का इस्तेमाल किया गया है. CursorLoader
अपनी क्वेरी, यूज़र इंटरफ़ेस (यूआई) थ्रेड से अलग किसी ऐसी थ्रेड पर चलाता है जो यूआई थ्रेड से अलग होती है. इससे यह पक्का होता है कि क्वेरी, यूज़र इंटरफ़ेस (यूआई) के रिस्पॉन्स में लगने वाले समय को कम करती है और उपयोगकर्ता को खराब अनुभव नहीं देती. ज़्यादा जानकारी के लिए, Android के लिए बनी ट्रेनिंग क्लास
बैकग्राउंड में डेटा लोड करना देखें.
सेवा देने वाली कंपनी की जानकारी पढ़ने की अनुमति का अनुरोध करना
संपर्क सूची में मौजूद किसी भी तरह की जानकारी खोजने के लिए, आपके ऐप्लिकेशन के पास
READ_CONTACTS
अनुमति होनी चाहिए.
इसका अनुरोध करने के लिए, अपनी मेनिफ़ेस्ट फ़ाइल में <uses-permission>
एलिमेंट को <manifest>
के चाइल्ड एलिमेंट के तौर पर जोड़ें:
<uses-permission android:name="android.permission.READ_CONTACTS" />
नाम के हिसाब से किसी संपर्क को मैच करना और नतीजों की सूची बनाना
इस तकनीक की मदद से, खोज स्ट्रिंग को संपर्क सेवा देने वाली कंपनी की ContactsContract.Contacts
टेबल में मौजूद किसी संपर्क या संपर्कों के नाम से मैच करने की कोशिश की जाती है. आम तौर पर, आपको नतीजों को ListView
में दिखाना होता है, ताकि उपयोगकर्ता मैच होने वाले संपर्कों में से किसी एक को चुन सके.
ListView और आइटम लेआउट तय करें
ListView
में खोज के नतीजे दिखाने के लिए, आपको एक मुख्य लेआउट फ़ाइल की ज़रूरत होती है. इसमें ListView
के साथ-साथ पूरे यूज़र इंटरफ़ेस (यूआई) की जानकारी होती है. साथ ही, एक आइटम लेआउट फ़ाइल की ज़रूरत होती है, जिसमें ListView
की एक लाइन की जानकारी होती है. उदाहरण के लिए, यहां दिए गए एक्सएमएल की मदद से, मुख्य लेआउट फ़ाइल res/layout/contacts_list_view.xml
बनाई जा सकती है:
<?xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent"/>
यह एक्सएमएल, पहले से मौजूद Android ListView
विजेट
android:id/list
का इस्तेमाल करता है.
आइटम लेआउट फ़ाइल contacts_list_item.xml
को यहां दिए गए एक्सएमएल की मदद से तय करें:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:clickable="true"/>
यह एक्सएमएल, डिवाइस में पहले से मौजूद Android TextView
विजेट का इस्तेमाल करता है
android:text1
.
ध्यान दें: इस लेसन में, उपयोगकर्ता से खोज स्ट्रिंग पाने के लिए यूज़र इंटरफ़ेस (यूआई) के बारे में नहीं बताया गया है, क्योंकि हो सकता है कि आप स्ट्रिंग को किसी और तरीके से पाना चाहें. उदाहरण के लिए, उपयोगकर्ता को उन संपर्कों को खोजने का विकल्प दिया जा सकता है जिनका नाम, इनकमिंग टेक्स्ट मैसेज में मौजूद स्ट्रिंग से मेल खाता है.
आपने जो दो लेआउट फ़ाइलें लिखी हैं वे एक ऐसे यूज़र इंटरफ़ेस की जानकारी देती हैं जिसमें एक
ListView
दिखता है. अगला चरण, कोड लिखना है. यह कोड, संपर्कों की सूची दिखाने के लिए इस यूज़र इंटरफ़ेस (यूआई) का इस्तेमाल करता है.
संपर्कों की सूची दिखाने वाला फ़्रैगमेंट तय करना
संपर्कों की सूची दिखाने के लिए, Activity
से लोड किए गए Fragment
को तय करें. Fragment
का इस्तेमाल करना, ज़्यादा सुविधाजनक तरीका है. इसकी वजह यह है कि सूची दिखाने के लिए एक Fragment
और सूची में से चुने गए संपर्क की जानकारी दिखाने के लिए एक दूसरा Fragment
इस्तेमाल किया जा सकता है. इस तरीके का इस्तेमाल करके, इस लेसन में दी गई एक तकनीक को
लेसन की एक तकनीक के साथ मिलाया जा सकता है.
किसी संपर्क की जानकारी वापस पाना.
किसी Activity
से एक या एक से ज़्यादा Fragment
ऑब्जेक्ट को इस्तेमाल करने का तरीका
जानने के लिए, ट्रेनिंग क्लास पढ़ें
फ़्रैगमेंट वाला डाइनैमिक यूज़र इंटरफ़ेस (यूआई) बनाएं.
संपर्क सूची की सेवा देने वाली कंपनी के लिए क्वेरी लिखने में आपकी मदद करने के लिए, Android फ़्रेमवर्क में ContactsContract
नाम की एक कॉन्ट्रैक्ट क्लास उपलब्ध होती है. इसमें, सेवा देने वाली कंपनी को ऐक्सेस करने के लिए, काम की स्थिर वैल्यू और तरीके बताए जाते हैं. इस क्लास का इस्तेमाल करने पर, आपको कॉन्टेंट यूआरआई, टेबल के नामों या कॉलम के लिए अपने कॉन्सटेंट तय करने की ज़रूरत नहीं होती है. इस क्लास का इस्तेमाल करने के लिए,
यह स्टेटमेंट शामिल करें:
Kotlin
import android.provider.ContactsContract
Java
import android.provider.ContactsContract;
कोड, डेटा पाने के लिए CursorLoader
का इस्तेमाल करता है. इसलिए, आपको यह बताना होगा कि यह लोडर इंटरफ़ेस LoaderManager.LoaderCallbacks
लागू करता है. साथ ही, खोज के नतीजों की सूची से उपयोगकर्ता ने कौनसा संपर्क चुना है, यह पता लगाने के लिए अडैप्टर इंटरफ़ेस AdapterView.OnItemClickListener
लागू करें. उदाहरण के लिए:
Kotlin
... import android.support.v4.app.Fragment import android.support.v4.app.LoaderManager import android.widget.AdapterView ... class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener {
Java
... import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.widget.AdapterView; ... public class ContactsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener {
ग्लोबल वैरिएबल तय करना
कोड के अन्य हिस्सों में इस्तेमाल किए जाने वाले ग्लोबल वैरिएबल तय करें:
Kotlin
... /* * Defines an array that contains column names to move from * the Cursor to the ListView. */ @SuppressLint("InlinedApi") private val FROM_COLUMNS: Array<String> = arrayOf( if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)) { ContactsContract.Contacts.DISPLAY_NAME_PRIMARY } else { ContactsContract.Contacts.DISPLAY_NAME } ) /* * Defines an array that contains resource ids for the layout views * that get the Cursor column contents. The id is pre-defined in * the Android framework, so it is prefaced with "android.R.id" */ private val TO_IDS: IntArray = intArrayOf(android.R.id.text1) ... class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener { ... // Define global mutable variables // Define a ListView object lateinit var contactsList: ListView // Define variables for the contact the user selects // The contact's _ID value var contactId: Long = 0 // The contact's LOOKUP_KEY var contactKey: String? = null // A content URI for the selected contact var contactUri: Uri? = null // An adapter that binds the result Cursor to the ListView private val cursorAdapter: SimpleCursorAdapter? = null
Java
... /* * Defines an array that contains column names to move from * the Cursor to the ListView. */ @SuppressLint("InlinedApi") private final static String[] FROM_COLUMNS = { Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME }; /* * Defines an array that contains resource ids for the layout views * that get the Cursor column contents. The id is pre-defined in * the Android framework, so it is prefaced with "android.R.id" */ private final static int[] TO_IDS = { android.R.id.text1 }; // Define global mutable variables // Define a ListView object ListView contactsList; // Define variables for the contact the user selects // The contact's _ID value long contactId; // The contact's LOOKUP_KEY String contactKey; // A content URI for the selected contact Uri contactUri; // An adapter that binds the result Cursor to the ListView private SimpleCursorAdapter cursorAdapter; ...
ध्यान दें: Contacts.DISPLAY_NAME_PRIMARY
के लिए, Android 3.0 (एपीआई वर्शन 11) या उसके बाद का वर्शन ज़रूरी है. इसलिए, अपने ऐप्लिकेशन के minSdkVersion
को 10 या उससे पहले के वर्शन पर सेट करने पर, Android Studio में Android Lint की चेतावनी जनरेट होती है. इस चेतावनी को बंद करने के लिए, FROM_COLUMNS
की परिभाषा से पहले एनोटेशन
@SuppressLint("InlinedApi")
जोड़ें.
फ़्रैगमेंट को शुरू करना
Fragment
को शुरू करें. Android सिस्टम के लिए ज़रूरी, खाली, सार्वजनिक कन्स्ट्रक्टर जोड़ें और कॉलबैक तरीके onCreateView()
में Fragment
ऑब्जेक्ट के यूआई को फ़्लोर करें.
उदाहरण के लिए:
Kotlin
// A UI Fragment must inflate its View override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the fragment layout return inflater.inflate(R.layout.contact_list_fragment, container, false) }
Java
// Empty public constructor, required by the system public ContactsFragment() {} // A UI Fragment must inflate its View @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the fragment layout return inflater.inflate(R.layout.contact_list_fragment, container, false); }
ListView के लिए CursorAdapter सेट अप करना
वह SimpleCursorAdapter
सेट अप करें जो खोज के नतीजों को ListView
से बाइंड करता है. संपर्कों को दिखाने वाला ListView
ऑब्जेक्ट पाने के लिए, आपको Fragment
की पैरंट गतिविधि का इस्तेमाल करके Activity.findViewById()
को कॉल करना होगा. setAdapter()
को कॉल करते समय, माता-पिता की गतिविधि के Context
का इस्तेमाल करें.
उदाहरण के लिए:
Kotlin
override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) ... // Gets the ListView from the View list of the parent activity activity?.also { contactsList = it.findViewById<ListView>(R.id.contact_list_view) // Gets a CursorAdapter cursorAdapter = SimpleCursorAdapter( it, R.layout.contact_list_item, null, FROM_COLUMNS, TO_IDS, 0 ) // Sets the adapter for the ListView contactsList.adapter = cursorAdapter } }
Java
public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); ... // Gets the ListView from the View list of the parent activity contactsList = (ListView) getActivity().findViewById(R.layout.contact_list_view); // Gets a CursorAdapter cursorAdapter = new SimpleCursorAdapter( getActivity(), R.layout.contact_list_item, null, FROM_COLUMNS, TO_IDS, 0); // Sets the adapter for the ListView contactsList.setAdapter(cursorAdapter); }
चुने गए संपर्क के लिए, संपर्क सुनने वाला ऐप्लिकेशन सेट करना
खोज के नतीजे दिखाते समय, आम तौर पर उपयोगकर्ता को आगे की प्रोसेसिंग के लिए, एक संपर्क चुनने की अनुमति दी जाती है. उदाहरण के लिए, जब कोई उपयोगकर्ता किसी संपर्क पर क्लिक करता है, तो आपके पास मैप पर उस संपर्क का पता दिखाने का विकल्प होता है. इस सुविधा को उपलब्ध कराने के लिए, आपने पहले मौजूदा
Fragment
को क्लिक के लिसनर के तौर पर तय किया था. इसके लिए, आपने यह बताया था कि क्लास
AdapterView.OnItemClickListener
को लागू करती है. इस बारे में ज़्यादा जानकारी के लिए, संपर्कों की सूची दिखाने वाला फ़्रैगमेंट तय करना सेक्शन देखें.
लिसनर सेट अप करना जारी रखने के लिए, onActivityCreated()
में setOnItemClickListener()
तरीके को कॉल करके, उसे ListView
से बाइंड करें. उदाहरण के लिए:
Kotlin
fun onActivityCreated(savedInstanceState:Bundle) { ... // Set the item click listener to be the current fragment. contactsList.onItemClickListener = this ... }
Java
public void onActivityCreated(Bundle savedInstanceState) { ... // Set the item click listener to be the current fragment. contactsList.setOnItemClickListener(this); ... }
आपने बताया है कि मौजूदा Fragment
,
ListView
के लिए
OnItemClickListener
है. इसलिए, अब आपको ज़रूरी तरीका
onItemClick()
लागू करना होगा, जो
क्लिक इवेंट को मैनेज करता है. इसके बारे में अगले सेक्शन में बताया गया है.
प्रक्षेप को परिभाषित करें
एक ऐसा कॉन्स्टेंट तय करें जिसमें वे कॉलम शामिल हों जिन्हें आपको अपनी क्वेरी से दिखाना है. ListView
में मौजूद हर आइटम में, संपर्क का डिसप्ले नेम दिखता है. इसमें संपर्क के नाम का मुख्य फ़ॉर्म होता है. Android 3.0 (एपीआई वर्शन 11) और उसके बाद के वर्शन में,
इस कॉलम का नाम
Contacts.DISPLAY_NAME_PRIMARY
है. इससे पहले के वर्शन में, इस कॉलम का नाम Contacts.DISPLAY_NAME
है.
कॉलम Contacts._ID
का इस्तेमाल,
SimpleCursorAdapter
बाइंडिंग प्रोसेस करती है.
Contacts._ID
और
LOOKUP_KEY
का एक साथ इस्तेमाल करके,
उपयोगकर्ता के चुने गए संपर्क का कॉन्टेंट यूआरआई बनाया जाता है.
Kotlin
... @SuppressLint("InlinedApi") private val PROJECTION: Array<out String> = arrayOf( ContactsContract.Contacts._ID, ContactsContract.Contacts.LOOKUP_KEY, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) ContactsContract.Contacts.DISPLAY_NAME_PRIMARY else ContactsContract.Contacts.DISPLAY_NAME )
Java
... @SuppressLint("InlinedApi") private static final String[] PROJECTION = { Contacts._ID, Contacts.LOOKUP_KEY, Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME };
कर्सर कॉलम इंडेक्स के लिए कॉन्स्टेंट तय करना
Cursor
में किसी कॉलम का डेटा पाने के लिए, आपके पास
Cursor
में कॉलम का इंडेक्स होना चाहिए. Cursor
कॉलम के इंडेक्स के लिए, आपके पास स्थिर वैल्यू तय करने का विकल्प होता है. ऐसा इसलिए, क्योंकि इंडेक्स, आपके प्रोजेक्शन में कॉलम के नामों के क्रम के जैसे ही होते हैं. उदाहरण के लिए:
Kotlin
// The column index for the _ID column private const val CONTACT_ID_INDEX: Int = 0 // The column index for the CONTACT_KEY column private const val CONTACT_KEY_INDEX: Int = 1
Java
// The column index for the _ID column private static final int CONTACT_ID_INDEX = 0; // The column index for the CONTACT_KEY column private static final int CONTACT_KEY_INDEX = 1;
चुनने की ज़रूरी शर्तें बताना
अपनी पसंद का डेटा पाने के लिए, टेक्स्ट एक्सप्रेशन और वैरिएबल का कॉम्बिनेशन बनाएं. इससे, डेटा प्रोवाइडर को यह पता चलता है कि कौनसे डेटा कॉलम खोजे जाएं और कौनसी वैल्यू ढूंढी जाएं.
टेक्स्ट एक्सप्रेशन के लिए, एक ऐसा कॉन्स्टेंट तय करें जिसमें खोज कॉलम की सूची हो. इस एक्सप्रेशन में वैल्यू भी हो सकती हैं. हालांकि, वैल्यू को "?" प्लेसहोल्डर के साथ दिखाना बेहतर होता है. जानकारी वापस पाने के दौरान, प्लेसहोल्डर को ऐरे की वैल्यू से बदल दिया जाता है. प्लेसहोल्डर के तौर पर "?" का इस्तेमाल करने से यह पक्का होता है कि खोज स्पेसिफ़िकेशन, एसक्यूएल कंपाइलेशन के बजाय बिडिंग से जनरेट किया गया है. इस तरीके से नुकसान पहुंचाने वाले एसक्यूएल इंजेक्शन की संभावना खत्म हो जाती है. उदाहरण के लिए:
Kotlin
// Defines the text expression @SuppressLint("InlinedApi") private val SELECTION: String = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) "${ContactsContract.Contacts.DISPLAY_NAME_PRIMARY} LIKE ?" else "${ContactsContract.Contacts.DISPLAY_NAME} LIKE ?" ... // Defines a variable for the search string private val searchString: String = ... // Defines the array to hold values that replace the ? private val selectionArgs = arrayOf<String>(searchString)
Java
// Defines the text expression @SuppressLint("InlinedApi") private static final String SELECTION = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?" : Contacts.DISPLAY_NAME + " LIKE ?"; // Defines a variable for the search string private String searchString; // Defines the array to hold values that replace the ? private String[] selectionArgs = { searchString };
onItemClick() तरीका तय करें
पिछले सेक्शन में, आपने ListView
के लिए आइटम क्लिक लिसनर सेट किया था.
अब लिसनर के लिए कार्रवाई लागू करें. इसके लिए, तरीका तय करें
AdapterView.OnItemClickListener.onItemClick()
:
Kotlin
override fun onItemClick(parent: AdapterView<*>, view: View?, position: Int, id: Long) { // Get the Cursor val cursor: Cursor? = (parent.adapter as? CursorAdapter)?.cursor?.apply { // Move to the selected contact moveToPosition(position) // Get the _ID value contactId = getLong(CONTACT_ID_INDEX) // Get the selected LOOKUP KEY contactKey = getString(CONTACT_KEY_INDEX) // Create the contact's content Uri contactUri = ContactsContract.Contacts.getLookupUri(contactId, mContactKey) /* * You can use contactUri as the content URI for retrieving * the details for a contact. */ } }
Java
@Override public void onItemClick( AdapterView<?> parent, View item, int position, long rowID) { // Get the Cursor Cursor cursor = parent.getAdapter().getCursor(); // Move to the selected contact cursor.moveToPosition(position); // Get the _ID value contactId = cursor.getLong(CONTACT_ID_INDEX); // Get the selected LOOKUP KEY contactKey = cursor.getString(CONTACT_KEY_INDEX); // Create the contact's content Uri contactUri = Contacts.getLookupUri(contactId, mContactKey); /* * You can use contactUri as the content URI for retrieving * the details for a contact. */ }
लोडर को शुरू करना
डेटा पाने के लिए CursorLoader
का इस्तेमाल किया जा रहा है. इसलिए, आपको बैकग्राउंड थ्रेड और ऐसे अन्य वैरिएबल को शुरू करना होगा जो डेटा को असाइनोसाइनक तरीके से पाने की प्रोसेस को कंट्रोल करते हैं. onCreate()
में, इस उदाहरण में दिखाए गए तरीके से शुरू करें:
Kotlin
class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor> { ... override fun onCreate(savedInstanceState: Bundle?) { // Always call the super method first super.onCreate(savedInstanceState) ... // Initializes the loader loaderManager.initLoader(0, null, this)
Java
public class ContactsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { ... // Called just before the Fragment displays its UI @Override public void onCreate(Bundle savedInstanceState) { // Always call the super method first super.onCreate(savedInstanceState); ... // Initializes the loader getLoaderManager().initLoader(0, null, this);
onCreateLoader() लागू करें
onCreateLoader()
वाला तरीका लागू करें. इसे initLoader()
को कॉल करने के तुरंत बाद, लोडर फ़्रेमवर्क कॉल करता है.
onCreateLoader()
में,
खोज स्ट्रिंग का पैटर्न सेट अप करें. किसी स्ट्रिंग को पैटर्न में बदलने के लिए, शून्य या उससे ज़्यादा वर्णों के क्रम को दिखाने के लिए "%" (प्रतिशत) कैरेक्टर या एक वर्ण को दिखाने के लिए "_" (अंडरस्कोर) कैरेक्टर डालें. इसके अलावा, दोनों कैरेक्टर भी डाले जा सकते हैं. उदाहरण के लिए, "%Jefferson%" पैटर्न, "Thomas Jefferson" और "Jefferson Davis", दोनों से मैच करेगा.
तरीके से नया CursorLoader
दें. कॉन्टेंट के यूआरआई के लिए, Contacts.CONTENT_URI
का इस्तेमाल करें.
यह यूआरआई, पूरी टेबल को रेफ़र करता है, जैसा कि नीचे दिए गए उदाहरण में दिखाया गया है:
Kotlin
... override fun onCreateLoader(loaderId: Int, args: Bundle?): Loader<Cursor> { /* * Makes search string into pattern and * stores it in the selection array */ selectionArgs[0] = "%$mSearchString%" // Starts the query return activity?.let { return CursorLoader( it, ContactsContract.Contacts.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ) } ?: throw IllegalStateException() }
Java
... @Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { /* * Makes search string into pattern and * stores it in the selection array */ selectionArgs[0] = "%" + searchString + "%"; // Starts the query return new CursorLoader( getActivity(), ContactsContract.Contacts.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ); }
onLoadFinished() और onLoaderReset() लागू करना
onLoadFinished()
वाला तरीका लागू करें. जब Contacts Provider, क्वेरी के नतीजे दिखाता है, तो लोडर फ़्रेमवर्क,
onLoadFinished()
को कॉल करता है. इस तरीके में, Cursor
को SimpleCursorAdapter
में डालें. इससे खोज के नतीजों के साथ,
ListView
अपने-आप अपडेट हो जाता है:
Kotlin
override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor) { // Put the result Cursor in the adapter for the ListView cursorAdapter?.swapCursor(cursor) }
Java
@Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { // Put the result Cursor in the adapter for the ListView cursorAdapter.swapCursor(cursor); }
जब लोडर फ़्रेमवर्क को पता चलता है कि Cursor
नतीजे में पुराना डेटा है, तो onLoaderReset()
तरीके को लागू किया जाता है. मौजूदा
Cursor
का
SimpleCursorAdapter
रेफ़रंस मिटाएं. ऐसा न करने पर, लोडर फ़्रेमवर्क Cursor
को फिर से इस्तेमाल नहीं करेगा. इसकी वजह से, मेमोरी लीक हो सकती है. उदाहरण के लिए:
Kotlin
override fun onLoaderReset(loader: Loader<Cursor>) { // Delete the reference to the existing Cursor cursorAdapter?.swapCursor(null) }
Java
@Override public void onLoaderReset(Loader<Cursor> loader) { // Delete the reference to the existing Cursor cursorAdapter.swapCursor(null); }
अब आपके पास ऐसे ऐप्लिकेशन के मुख्य हिस्से हैं जो खोज स्ट्रिंग को संपर्क के नाम से मैच करता है और ListView
में नतीजा दिखाता है. उपयोगकर्ता, किसी संपर्क के नाम पर क्लिक करके उसे चुन सकता है.
इससे एक लिसनर ट्रिगर होता है, जिसमें संपर्क के डेटा के साथ आगे काम किया जा सकता है. उदाहरण के लिए,
आप संपर्क की जानकारी वापस पा सकते हैं. इसका तरीका जानने के लिए, अगले
लेसन किसी संपर्क की जानकारी वापस पाना को जारी रखें.
खोज के यूज़र इंटरफ़ेस के बारे में ज़्यादा जानने के लिए, एपीआई गाइड पढ़ें खोज इंटरफ़ेस बनाना.
इस लेसन के बाकी सेक्शन में, संपर्कों की जानकारी देने वाली सेवा देने वाली कंपनी के संपर्कों को ढूंढने के अन्य तरीकों के बारे में बताया गया है.
किसी खास तरह के डेटा के हिसाब से संपर्क को मैच करना
इस तकनीक की मदद से, यह तय किया जा सकता है कि आपको किस तरह का डेटा मैच करना है. इस तरह की क्वेरी का एक खास उदाहरण है कि यूआरएल का इस्तेमाल करके वापस लाया जा सकता है. हालांकि, संपर्क से जुड़ी किसी भी तरह की जानकारी वाले डेटा के लिए भी ऐसा किया जा सकता है. उदाहरण के लिए, ऐसे संपर्कों को ढूंढा जा सकता है जिनका पिन कोड एक जैसा हो. इस मामले में, खोज स्ट्रिंग को पिन कोड वाली पंक्ति में सेव किए गए डेटा से मैच करना होगा.
इस तरह की जानकारी वापस पाने के लिए, पहले पिछले सेक्शन में दिए गए कोड को लागू करें:
- सेवा देने वाली कंपनी की जानकारी पढ़ने की अनुमति का अनुरोध करें.
- ListView और आइटम लेआउट तय करें.
- संपर्कों की सूची दिखाने वाला फ़्रैगमेंट तय करें.
- ग्लोबल वैरिएबल तय करें.
- फ़्रैगमेंट को शुरू करें.
- ListView के लिए CursorAdapter सेट अप करें.
- चुने गए संपर्क के लिए, संपर्क सुनने वाला ऐप्लिकेशन सेट करें.
-
कर्सर कॉलम इंडेक्स के लिए, कॉन्स्टेंट तय करें.
हालांकि, किसी दूसरी टेबल से डेटा फ़ेच किया जाता है, लेकिन प्रोजेक्शन में कॉलम का क्रम एक जैसा होता है. इसलिए, कर्सर के लिए एक जैसे इंडेक्स का इस्तेमाल किया जा सकता है.
- onItemClick() मेथड तय करें.
- लोडर को शुरू करें.
- onLoadFinished() और onLoaderReset() लागू करें.
यहां दिए गए चरणों में, आपको अतिरिक्त कोड के बारे में बताया गया है. इस कोड की मदद से, किसी खोज स्ट्रिंग को किसी खास तरह के ज़्यादा जानकारी वाले डेटा से मैच किया जा सकता है और नतीजे दिखाए जा सकते हैं.
डेटा टाइप और टेबल चुनें
किसी खास तरह की जानकारी वाला डेटा खोजने के लिए, आपके पास डेटा टाइप के लिए पसंद के मुताबिक MIME टाइप वैल्यू
होनी चाहिए. हर डेटा टाइप के लिए, एक यूनीक MIME टाइप की वैल्यू होती है. यह वैल्यू, डेटा टाइप से जुड़े ContactsContract.CommonDataKinds
के सबक्लास में मौजूद कॉन्स्टेंट CONTENT_ITEM_TYPE
से तय होती है.
सबक्लास के नाम से उनके डेटा टाइप का पता चलता है. उदाहरण के लिए, ईमेल डेटा के लिए सबक्लास ContactsContract.CommonDataKinds.Email
है और ईमेल डेटा के लिए कस्टम MIME टाइप को स्थिर वैल्यू Email.CONTENT_ITEM_TYPE
से तय किया जाता है.
अपनी खोज के लिए, ContactsContract.Data
टेबल का इस्तेमाल करें. प्रोजेक्शन, चुनने के क्लॉज़, और क्रम से लगाने के लिए ज़रूरी सभी कॉन्स्टेंट, इस टेबल में तय किए जाते हैं या इनहेरिट किए जाते हैं.
प्रोजेक्शन तय करना
प्रोजेक्शन के बारे में बताने के लिए, ContactsContract.Data
में बताए गए एक या उससे ज़्यादा कॉलम या उन क्लास को चुनें जिनसे इसे इनहेरिट किया जाता है. कॉन्टैक्ट की जानकारी देने वाली सेवा देने वाली कंपनी, पंक्तियां दिखाने से पहले ContactsContract.Data
और अन्य टेबल के बीच इंप्लिसिट जॉइन करती है. उदाहरण के लिए:
Kotlin
@SuppressLint("InlinedApi") private val PROJECTION: Array<out String> = arrayOf( /* * The detail data row ID. To make a ListView work, * this column is required. */ ContactsContract.Data._ID, // The primary display name if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) ContactsContract.Data.DISPLAY_NAME_PRIMARY else ContactsContract.Data.DISPLAY_NAME, // The contact's _ID, to construct a content URI ContactsContract.Data.CONTACT_ID, // The contact's LOOKUP_KEY, to construct a content URI ContactsContract.Data.LOOKUP_KEY )
Java
@SuppressLint("InlinedApi") private static final String[] PROJECTION = { /* * The detail data row ID. To make a ListView work, * this column is required. */ ContactsContract.Data._ID, // The primary display name Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? ContactsContract.Data.DISPLAY_NAME_PRIMARY : ContactsContract.Data.DISPLAY_NAME, // The contact's _ID, to construct a content URI ContactsContract.Data.CONTACT_ID, // The contact's LOOKUP_KEY, to construct a content URI ContactsContract.Data.LOOKUP_KEY // A permanent link to the contact };
खोज की शर्तें तय करना
किसी खास तरह के डेटा में कोई स्ट्रिंग खोजने के लिए, इनमें से कोई एक सिलेक्शन क्लॉज़ बनाएं:
-
उस कॉलम का नाम जिसमें आपकी खोज स्ट्रिंग शामिल है. यह नाम डेटा टाइप के हिसाब से अलग-अलग होता है. इसलिए, आपको डेटा टाइप से जुड़ा
ContactsContract.CommonDataKinds
का सबक्लास ढूंढना होगा. इसके बाद, उस सबक्लास से कॉलम का नाम चुनना होगा. उदाहरण के लिए, ईमेल पते खोजने के लिए, कॉलमEmail.ADDRESS
का इस्तेमाल करें. - खोज स्ट्रिंग, जो सिलेक्शन क्लॉज़ में "?" वर्ण के तौर पर दिखती है.
-
उस कॉलम का नाम जिसमें कस्टम MIME टाइप की वैल्यू मौजूद है. यह नाम हमेशा
Data.MIMETYPE
होता है. -
डेटा टाइप के लिए कस्टम MIME टाइप की वैल्यू. जैसा कि पहले बताया गया है, यह
ContactsContract.CommonDataKinds
सबक्लास में मौजूद,CONTENT_ITEM_TYPE
कॉन्स्टेंट है. उदाहरण के लिए, ईमेल डेटा के लिए MIME टाइप की वैल्यूEmail.CONTENT_ITEM_TYPE
है. वैल्यू को सिंगल कोट में रखने के लिए, "'
" (सिंगल कोट) वर्ण को कॉन्स्टेंट के शुरू और आखिर में जोड़ें. ऐसा न करने पर, सेवा देने वाला, वैल्यू को स्ट्रिंग की वैल्यू के बजाय वैरिएबल के नाम के तौर पर समझता है. आपको इस वैल्यू के लिए प्लेसहोल्डर का इस्तेमाल करने की ज़रूरत नहीं है, क्योंकि उपयोगकर्ता की दी गई वैल्यू के बजाय, आपने एक स्थिर वैल्यू का इस्तेमाल किया है.
उदाहरण के लिए:
Kotlin
/* * Constructs search criteria from the search string * and email MIME type */ private val SELECTION: String = /* * Searches for an email address * that matches the search string */ "${Email.ADDRESS} LIKE ? AND " + /* * Searches for a MIME type that matches * the value of the constant * Email.CONTENT_ITEM_TYPE. Note the * single quotes surrounding Email.CONTENT_ITEM_TYPE. */ "${ContactsContract.Data.MIMETYPE } = '${Email.CONTENT_ITEM_TYPE}'"
Java
/* * Constructs search criteria from the search string * and email MIME type */ private static final String SELECTION = /* * Searches for an email address * that matches the search string */ Email.ADDRESS + " LIKE ? " + "AND " + /* * Searches for a MIME type that matches * the value of the constant * Email.CONTENT_ITEM_TYPE. Note the * single quotes surrounding Email.CONTENT_ITEM_TYPE. */ ContactsContract.Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'";
इसके बाद, वैरिएबल तय करें, ताकि उनमें सिलेक्शन आर्ग्युमेंट शामिल किया जा सके:
Kotlin
private var searchString: String? = null private val selectionArgs: Array<String> = arrayOf("")
Java
String searchString; String[] selectionArgs = { "" };
onCreateLoader() लागू करें
अब आपने वह डेटा और उसे ढूंढने का तरीका तय कर लिया है. अब onCreateLoader()
को लागू करने के लिए, एक क्वेरी तय करें.
इस तरीके से एक नया CursorLoader
दिखाएं. इसके लिए, अपने प्रोजेक्शन, चुने गए टेक्स्ट एक्सप्रेशन, और चुने गए अरे का इस्तेमाल, आर्ग्युमेंट के तौर पर करें. कॉन्टेंट यूआरआई के लिए, Data.CONTENT_URI
का इस्तेमाल करें. उदाहरण के लिए:
Kotlin
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> { // OPTIONAL: Makes search string into pattern searchString = "%$mSearchString%" searchString?.also { // Puts the search string into the selection criteria selectionArgs[0] = it } // Starts the query return activity?.let { CursorLoader( it, ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ) } ?: throw IllegalStateException() }
Java
@Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { // OPTIONAL: Makes search string into pattern searchString = "%" + searchString + "%"; // Puts the search string into the selection criteria selectionArgs[0] = searchString; // Starts the query return new CursorLoader( getActivity(), Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ); }
ये कोड स्निपेट, किसी खास तरह के ज़्यादा जानकारी वाले डेटा के आधार पर, रिवर्स लुकअप के लिए इस्तेमाल किए जाते हैं. अगर आपका ऐप्लिकेशन किसी खास तरह के डेटा पर फ़ोकस करता है, जैसे कि ईमेल, और आपको उपयोगकर्ताओं को किसी डेटा से जुड़े नामों को पाने की अनुमति देनी है, तो यह सबसे सही तरीका है.
किसी भी तरह के डेटा से संपर्क को मैच करना
किसी भी तरह के डेटा के आधार पर संपर्क खोजने पर, वे संपर्क दिखते हैं जिनका कोई डेटा खोज स्ट्रिंग से मैच करता है. इसमें नाम, ईमेल पता, डाक पता, फ़ोन नंबर वगैरह शामिल हैं. इससे खोज के नतीजों का दायरा बड़ा हो जाता है. उदाहरण के लिए, अगर खोज स्ट्रिंग "डो" है, तो किसी भी डेटा टाइप को खोजने पर, "जॉन डो" नाम का संपर्क दिखता है. साथ ही, "डो स्ट्रीट" पर रहने वाले संपर्क भी दिखते हैं.
इस तरह की जानकारी वापस पाने के लिए, पहले पिछले सेक्शन में दिए गए कोड को लागू करें:
- सेवा देने वाली कंपनी की जानकारी पढ़ने की अनुमति का अनुरोध करें.
- ListView और आइटम लेआउट तय करें.
- संपर्कों की सूची दिखाने वाला फ़्रैगमेंट तय करें.
- ग्लोबल वैरिएबल तय करें.
- फ़्रैगमेंट को शुरू करें.
- ListView के लिए CursorAdapter सेट अप करें.
- चुने गए संपर्क के लिए, संपर्क सुनने वाला ऐप्लिकेशन सेट करें.
- प्रोजेक्शन तय करना.
-
कर्सर कॉलम इंडेक्स के लिए, कॉन्स्टेंट तय करें.
इस तरह से संपर्क जानकारी वापस पाने के लिए, उसी टेबल का इस्तेमाल किया जा रहा है जिसका इस्तेमाल आपने संपर्क जानकारी को नाम से मैच करने और नतीजों की सूची बनाने वाले सेक्शन में किया था. एक ही कॉलम के इंडेक्स का भी इस्तेमाल करें.
- onItemClick() मेथड तय करें.
- लोडर को शुरू करें.
- onLoadFinished() और onLoaderReset() लागू करें.
यहां दिए गए चरणों में, आपको वह अतिरिक्त कोड दिखेगा जिसकी ज़रूरत किसी भी तरह के डेटा के साथ खोज स्ट्रिंग को मैच करने और नतीजे दिखाने के लिए होती है.
चुनने के लिए ज़रूरी शर्तें हटाएं
SELECTION
कॉन्स्टेंट या mSelectionArgs
वैरिएबल तय न करें.
इस तरह के डेटा को वापस पाने के लिए, इनका इस्तेमाल नहीं किया जाता.
onCreateLoader() लागू करें
onCreateLoader()
तरीका लागू करें, जो नया CursorLoader
दिखाता है.
आपको खोज स्ट्रिंग को पैटर्न में बदलने की ज़रूरत नहीं है, क्योंकि संपर्कों की जानकारी देने वाली सेवा देने वाली कंपनी, ऐसा अपने-आप करती है. Contacts.CONTENT_FILTER_URI
को बेस यूआरआई के तौर पर इस्तेमाल करें और Uri.withAppendedPath()
को कॉल करके, अपनी खोज स्ट्रिंग को उसमें जोड़ें. इस यूआरआई का इस्तेमाल करने पर, किसी भी डेटा टाइप के लिए खोज अपने-आप ट्रिगर हो जाती है. इसका उदाहरण यहां दिया गया है:
Kotlin
override fun onCreateLoader(loaderId: Int, args: Bundle?): Loader<Cursor> { /* * Appends the search string to the base URI. Always * encode search strings to ensure they're in proper * format. */ val contentUri: Uri = Uri.withAppendedPath( ContactsContract.Contacts.CONTENT_FILTER_URI, Uri.encode(searchString) ) // Starts the query return activity?.let { CursorLoader( it, contentUri, PROJECTION2, null, null, null ) } ?: throw IllegalStateException() }
Java
@Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { /* * Appends the search string to the base URI. Always * encode search strings to ensure they're in proper * format. */ Uri contentUri = Uri.withAppendedPath( Contacts.CONTENT_FILTER_URI, Uri.encode(searchString)); // Starts the query return new CursorLoader( getActivity(), contentUri, PROJECTION, null, null, null ); }
ये कोड स्निपेट, ऐसे ऐप्लिकेशन के आधार हैं जो संपर्कों की जानकारी देने वाली सेवा देने वाली कंपनी की जानकारी को बड़े पैमाने पर खोजता है. यह तरीका उन ऐप्लिकेशन के लिए फ़ायदेमंद है जो People ऐप्लिकेशन की संपर्क सूची वाली स्क्रीन जैसी सुविधा लागू करना चाहते हैं.