इस लेसन में किसी संपर्क की ज़्यादा जानकारी वाला डेटा पाने का तरीका बताया गया है. जैसे, ईमेल पते, फ़ोन नंबर वगैरह. संपर्क को फिर से पाने के लिए, उपयोगकर्ताओं को यही जानकारी चाहिए होती है. आपके पास किसी संपर्क की पूरी जानकारी देने या सिर्फ़ किसी खास तरह की जानकारी दिखाने का विकल्प होता है. जैसे, ईमेल पते.
इस लेसन में दिए गए चरण यह मानते हैं कि उपयोगकर्ता के चुने गए संपर्क के लिए, आपके पास पहले से ही एक ContactsContract.Contacts
लाइन है.
संपर्क के नाम वापस पाना लेसन में, संपर्कों की सूची
वापस पाने का तरीका बताया गया है.
किसी संपर्क की पूरी जानकारी पाना
किसी संपर्क की पूरी जानकारी पाने के लिए, ContactsContract.Data
टेबल में ऐसी सभी पंक्तियां खोजें जिनमें संपर्क का LOOKUP_KEY
शामिल हो. यह कॉलम ContactsContract.Data
टेबल में उपलब्ध है, क्योंकि संपर्कों की जानकारी देने वाली सेवा, ContactsContract.Contacts
टेबल और ContactsContract.Data
टेबल के बीच एक इनपुट जॉइन बनाती है. LOOKUP_KEY
कॉलम के बारे में, संपर्क के नाम वापस पाना लेसन में ज़्यादा जानकारी दी गई है.
ध्यान दें: किसी संपर्क की पूरी जानकारी हासिल करने से, डिवाइस की परफ़ॉर्मेंस पर असर पड़ता है. ऐसा इसलिए होता है, क्योंकि इसके लिए ContactsContract.Data
टेबल के सभी कॉलम को हासिल करना पड़ता है. इस तकनीक का इस्तेमाल करने से पहले, परफ़ॉर्मेंस पर पड़ने वाले असर पर विचार करें.
अनुमतियों का अनुरोध करना
संपर्कों की जानकारी देने वाली सेवा से संपर्कों की जानकारी पढ़ने के लिए, आपके ऐप्लिकेशन के पास
READ_CONTACTS
अनुमति होनी चाहिए.
इस अनुमति का अनुरोध करने के लिए, अपनी मेनिफ़ेस्ट फ़ाइल में
<manifest>
का यह चाइल्ड एलिमेंट जोड़ें:
<uses-permission android:name="android.permission.READ_CONTACTS" />
प्रोजेक्शन सेट अप करना
किसी पंक्ति में मौजूद डेटा टाइप के आधार पर, वह सिर्फ़ कुछ या कई कॉलम का इस्तेमाल कर सकती है. इसके अलावा,
डेटा टाइप के आधार पर डेटा अलग-अलग कॉलम में होता है.
यह पक्का करने के लिए कि आपको सभी संभावित डेटा टाइप के लिए सभी संभावित कॉलम मिलें, आपको अपने प्रोजेक्शन में सभी कॉलम के नाम जोड़ने होंगे. अगर नतीजे Cursor
को ListView
से बांधना है, तो हमेशा Data._ID
को फिर से पाएं. ऐसा न करने पर, बांधने की सुविधा काम नहीं करेगी. Data.MIMETYPE
को भी वापस लाएं
ताकि आप वापस लाई गई हर पंक्ति के डेटा टाइप की पहचान कर सकें. उदाहरण के लिए:
Kotlin
private val PROJECTION: Array<out String> = arrayOf( ContactsContract.Data._ID, ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1, ContactsContract.Data.DATA2, ContactsContract.Data.DATA3, ContactsContract.Data.DATA4, ContactsContract.Data.DATA5, ContactsContract.Data.DATA6, ContactsContract.Data.DATA7, ContactsContract.Data.DATA8, ContactsContract.Data.DATA9, ContactsContract.Data.DATA10, ContactsContract.Data.DATA11, ContactsContract.Data.DATA12, ContactsContract.Data.DATA13, ContactsContract.Data.DATA14, ContactsContract.Data.DATA15 )
Java
private static final String[] PROJECTION = { ContactsContract.Data._ID, ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1, ContactsContract.Data.DATA2, ContactsContract.Data.DATA3, ContactsContract.Data.DATA4, ContactsContract.Data.DATA5, ContactsContract.Data.DATA6, ContactsContract.Data.DATA7, ContactsContract.Data.DATA8, ContactsContract.Data.DATA9, ContactsContract.Data.DATA10, ContactsContract.Data.DATA11, ContactsContract.Data.DATA12, ContactsContract.Data.DATA13, ContactsContract.Data.DATA14, ContactsContract.Data.DATA15 };
यह प्रोजेक्शन, ContactsContract.Data
क्लास में तय किए गए कॉलम के नामों का इस्तेमाल करके, ContactsContract.Data
टेबल में किसी पंक्ति के सभी कॉलम को फिर से पाता है.
इसके अलावा, ContactsContract.Data
क्लास में तय की गई या उससे इनहेरिट की गई किसी भी कॉलम कॉन्स्टेंट का इस्तेमाल भी किया जा सकता है. हालांकि, ध्यान दें कि SYNC1
से लेकर
SYNC4
तक के कॉलम का इस्तेमाल, सिंक करने वाले ऐडैप्टर करते हैं. इसलिए, इनका डेटा काम का नहीं होता.
चुनने की ज़रूरी शर्तें तय करना
अपने सिलेक्शन क्लॉज़ के लिए एक कॉन्स्टेंट, सिलेक्शन के आर्ग्युमेंट को सेव करने के लिए एक कलेक्शन, और सिलेक्शन की वैल्यू को सेव करने के लिए एक वैरिएबल तय करें. संपर्क
ढूंढने के लिए,
Contacts.LOOKUP_KEY
कॉलम
का इस्तेमाल करें. उदाहरण के लिए:
Kotlin
// Defines the selection clause private const val SELECTION: String = "${ContactsContract.Data.LOOKUP_KEY} = ?" ... // Defines the array to hold the search criteria private val selectionArgs: Array<String> = arrayOf("") /* * Defines a variable to contain the selection value. Once you * have the Cursor from the Contacts table, and you've selected * the desired row, move the row's LOOKUP_KEY value into this * variable. */ private var lookupKey: String? = null
Java
// Defines the selection clause private static final String SELECTION = Data.LOOKUP_KEY + " = ?"; // Defines the array to hold the search criteria private String[] selectionArgs = { "" }; /* * Defines a variable to contain the selection value. Once you * have the Cursor from the Contacts table, and you've selected * the desired row, move the row's LOOKUP_KEY value into this * variable. */ private lateinit var lookupKey: String
अपने सिलेक्शन टेक्स्ट एक्सप्रेशन में प्लेसहोल्डर के तौर पर "?" का इस्तेमाल करने से, यह पक्का होता है कि खोज के नतीजे, SQL कंपाइलेशन के बजाय बिंडिंग से जनरेट किए जाते हैं. इस तरीके से, नुकसान पहुंचाने वाले एसक्यूएल इंजेक्शन की संभावना खत्म हो जाती है.
क्रम से लगाने का तरीका तय करना
Cursor
में, डेटा को क्रम से लगाने का तरीका तय करें. किसी खास डेटा टाइप की सभी पंक्तियों को एक साथ रखने के लिए, Data.MIMETYPE
के हिसाब से क्रम से लगाएं. यह क्वेरी आर्ग्युमेंट, सभी ईमेल पंक्तियों को एक साथ, सभी फ़ोन पंक्तियों को एक साथ वगैरह ग्रुप करता है. उदाहरण के लिए:
Kotlin
/* * Defines a string that specifies a sort order of MIME type */ private const val SORT_ORDER = ContactsContract.Data.MIMETYPE
Java
/* * Defines a string that specifies a sort order of MIME type */ private static final String SORT_ORDER = ContactsContract.Data.MIMETYPE;
ध्यान दें: कुछ डेटा टाइप, सब-टाइप का इस्तेमाल नहीं करते. इसलिए, सब-टाइप के हिसाब से क्रम से नहीं लगाया जा सकता.
इसके बजाय, आपको दिखाए गए Cursor
के ज़रिए,
मौजूदा लाइन का डेटा टाइप तय करना होगा. साथ ही, सब-टाइप का इस्तेमाल करने वाली लाइनों का डेटा स्टोर करना होगा. कर्सर को पढ़ने के बाद, हर डेटा टाइप को सब-टाइप के हिसाब से क्रम में लगाया जा सकता है और नतीजे दिखाए जा सकते हैं.
लोडर को शुरू करें
संपर्कों की जानकारी देने वाली कंपनी (और कॉन्टेंट की सेवा देने वाली सभी अन्य कंपनियों) से, हमेशा बैकग्राउंड थ्रेड में जानकारी पाएं. बैकग्राउंड में डेटा पाने के लिए,
LoaderManager
क्लास और
LoaderManager.LoaderCallbacks
इंटरफ़ेस से तय किए गए लोडर फ़्रेमवर्क का इस्तेमाल करें.
जब आप पंक्तियां वापस पाने के लिए तैयार हों, तो initLoader()
को कॉल करके, लोडर फ़्रेमवर्क को शुरू करें. तरीके में एक
पूर्णांक आइडेंटिफ़ायर पास करें; यह आइडेंटिफ़ायर,
LoaderManager.LoaderCallbacks
तरीकों को पास किया जाता है. आइडेंटिफ़ायर की मदद से, किसी ऐप्लिकेशन में एक से ज़्यादा लोडर का इस्तेमाल किया जा सकता है. इसके लिए, आपको अलग-अलग लोडर के बीच अंतर करना होगा.
यहां दिए गए स्निपेट में, लोडर फ़्रेमवर्क को शुरू करने का तरीका बताया गया है:
Kotlin
// Defines a constant that identifies the loader private const val DETAILS_QUERY_ID: Int = 0 class DetailsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor> { ... override fun onCreate(savedInstanceState: Bundle?) { ... // Initializes the loader framework loaderManager.initLoader(DETAILS_QUERY_ID, null, this)
Java
public class DetailsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { ... // Defines a constant that identifies the loader static int DETAILS_QUERY_ID = 0; ... @Override public void onCreate(Bundle savedInstanceState) { ... // Initializes the loader framework getLoaderManager().initLoader(DETAILS_QUERY_ID, null, this);
onCreateLoader() लागू करना
onCreateLoader()
का तरीका लागू करें. यह तरीका, initLoader()
को कॉल करने के तुरंत बाद, लोडर फ़्रेमवर्क से कॉल किया जाता है. इस तरीके से,
CursorLoader
दिखाएं. ContactsContract.Data
टेबल खोजने के लिए, कॉन्टेंट यूआरआई के तौर पर कॉन्स्टेंट Data.CONTENT_URI
का इस्तेमाल करें.
उदाहरण के लिए:
Kotlin
override fun onCreateLoader(loaderId: Int, args: Bundle?): Loader<Cursor> { // Choose the proper action mLoader = when(loaderId) { DETAILS_QUERY_ID -> { // Assigns the selection parameter selectionArgs[0] = lookupKey // Starts the query activity?.let { CursorLoader( it, ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, SORT_ORDER ) } } ... } return mLoader }
Java
@Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { // Choose the proper action switch (loaderId) { case DETAILS_QUERY_ID: // Assigns the selection parameter selectionArgs[0] = lookupKey; // Starts the query CursorLoader mLoader = new CursorLoader( getActivity(), ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, SORT_ORDER ); }
onLoadFinished() और onLoaderReset() लागू करना
onLoadFinished()
तरीका लागू करें. जब Contacts Provider, क्वेरी के नतीजे दिखाता है, तो लोडर फ़्रेमवर्क,
onLoadFinished()
को कॉल करता है. उदाहरण के लिए:
Kotlin
override fun onLoadFinished(loader: Loader<Cursor>, data: Cursor) { when(loader.id) { DETAILS_QUERY_ID -> { /* * Process the resulting Cursor here. */ } ... } }
Java
@Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { switch (loader.getId()) { case DETAILS_QUERY_ID: /* * Process the resulting Cursor here. */ } break; ... } }
onLoaderReset()
का तरीका तब लागू होता है, जब लोडर फ़्रेमवर्क को पता चलता है कि Cursor
के नतीजे का डेटा बदल गया है. ऐसा होने पर, Cursor
के सभी मौजूदा रेफ़रंस को शून्य पर सेट करके उन्हें हटा दें. ऐसा न करने पर, लोडर फ़्रेमवर्क, पुराने Cursor
को नष्ट नहीं करेगा और आपको मेमोरी लीक की समस्या होगी. उदाहरण के लिए:
Kotlin
override fun onLoaderReset(loader: Loader<Cursor>) { when (loader.id) { DETAILS_QUERY_ID -> { /* * If you have current references to the Cursor, * remove them here. */ } ... } }
Java
@Override public void onLoaderReset(Loader<Cursor> loader) { switch (loader.getId()) { case DETAILS_QUERY_ID: /* * If you have current references to the Cursor, * remove them here. */ } break; }
किसी संपर्क की खास जानकारी पाना
किसी संपर्क के लिए, सभी ईमेल जैसे किसी खास तरह का डेटा पाने के लिए, वही तरीका अपनाएं जो सभी जानकारी पाने के लिए अपनाया जाता है. किसी संपर्क की पूरी जानकारी पाना में दिए गए कोड में, आपको सिर्फ़ ये बदलाव करने होंगे:
- अनुमान
-
डेटा टाइप के हिसाब से कॉलम पाने के लिए, अपने प्रोजेक्शन में बदलाव करें. डेटा टाइप से जुड़े
ContactsContract.CommonDataKinds
सबक्लास में तय किए गए कॉलम के नाम के कॉन्स्टेंट का इस्तेमाल करने के लिए, प्रोजेक्शन में भी बदलाव करें. - चुनें
-
अपने डेटा टाइप के हिसाब से
MIMETYPE
वैल्यू खोजने के लिए, चुने गए टेक्स्ट में बदलाव करें. - क्रमित करने का क्रम
-
सिर्फ़ एक तरह की जानकारी चुनने पर,
Data.MIMETYPE
के हिसाब से, रिटर्न किए गएCursor
को ग्रुप न करें.
इन बदलावों के बारे में नीचे दिए गए सेक्शन में बताया गया है.
प्रोजेक्शन तय करना
डेटा टाइप के लिए ContactsContract.CommonDataKinds
के सबक्लास में, कॉलम के नाम के कॉन्स्टेंट का इस्तेमाल करके, उन कॉलम को तय करें जिन्हें आपको फिर से पाना है.
अगर आपको अपने Cursor
को किसी ListView
से बांधना है, तो
_ID
कॉलम को ज़रूर वापस पाएं. उदाहरण के लिए, ईमेल डेटा को वापस पाने के लिए, यह प्रोजेक्शन तय करें:
Kotlin
private val PROJECTION: Array<String> = arrayOf( ContactsContract.CommonDataKinds.Email._ID, ContactsContract.CommonDataKinds.Email.ADDRESS, ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.LABEL )
Java
private static final String[] PROJECTION = { ContactsContract.CommonDataKinds.Email._ID, ContactsContract.CommonDataKinds.Email.ADDRESS, ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.LABEL };
ध्यान दें कि यह प्रोजेक्शन, क्लास ContactsContract.Data
में तय किए गए कॉलम के नामों के बजाय, क्लास ContactsContract.CommonDataKinds.Email
में तय किए गए कॉलम के नामों का इस्तेमाल करता है. ईमेल के हिसाब से कॉलम के नाम इस्तेमाल करने से, कोड को पढ़ना आसान हो जाता है.
प्रोजेक्शन में, ContactsContract.CommonDataKinds
सबक्लास में तय किए गए किसी भी अन्य कॉलम का भी इस्तेमाल किया जा सकता है.
चुनने के लिए ज़रूरी शर्तें तय करें
खोज के लिए ऐसा टेक्स्ट एक्सप्रेशन तय करें जो किसी खास संपर्क के LOOKUP_KEY
और आपकी पसंद की जानकारी के Data.MIMETYPE
के लिए पंक्तियां ढूंढे. MIMETYPE
वैल्यू को सिंगल कोट में डालें. इसके लिए, कॉन्स्टेंट की शुरुआत और आखिर में "'
" (सिंगल कोट) वर्ण जोड़ें. ऐसा न करने पर, प्रोवाइडर कॉन्स्टेंट को स्ट्रिंग वैल्यू के बजाय वैरिएबल के नाम के तौर पर समझता है. इस वैल्यू के लिए आपको प्लेसहोल्डर का इस्तेमाल करने की ज़रूरत नहीं है, क्योंकि
उपयोगकर्ता से दी गई वैल्यू के बजाय, कॉन्स्टेंट का इस्तेमाल किया जा रहा है. उदाहरण के लिए:
Kotlin
/* * Defines the selection clause. Search for a lookup key * and the Email MIME type */ private const val SELECTION = "${ContactsContract.Data.LOOKUP_KEY} = ? AND " + "${ContactsContract.Data.MIMETYPE} = '${Email.CONTENT_ITEM_TYPE}'" ... // Defines the array to hold the search criteria private val selectionArgs: Array<String> = arrayOf("")
Java
/* * Defines the selection clause. Search for a lookup key * and the Email MIME type */ private static final String SELECTION = Data.LOOKUP_KEY + " = ?" + " AND " + Data.MIMETYPE + " = " + "'" + Email.CONTENT_ITEM_TYPE + "'"; // Defines the array to hold the search criteria private String[] selectionArgs = { "" };
क्रम तय करना
लौटाए गए Cursor
के लिए, क्रम तय करें. आपने किसी खास तरह का डेटा पाने के लिए, MIMETYPE
पर क्रम से लगाने का विकल्प नहीं चुना है.
इसके बजाय, अगर ज़्यादा जानकारी वाले जिस डेटा को खोजा जा रहा है उसमें कोई सब-टाइप शामिल है, तो उस पर क्रम से लगाएं.
उदाहरण के लिए, ईमेल डेटा के लिए,
Email.TYPE
पर क्रम से लगाया जा सकता है:
Kotlin
private const val SORT_ORDER: String = "${Email.TYPE} ASC"
Java
private static final String SORT_ORDER = Email.TYPE + " ASC ";