इस लेसन में, किसी संपर्क की ज़्यादा जानकारी वाले डेटा को वापस पाने का तरीका बताया गया है. जैसे, ईमेल पते, फ़ोन नंबर वगैरह. यह वह जानकारी होती है जिसे उपयोगकर्ता किसी संपर्क को खोजते समय देखना चाहते हैं. आपके पास किसी संपर्क की पूरी जानकारी देने या सिर्फ़ किसी खास तरह की जानकारी दिखाने का विकल्प होता है. जैसे, ईमेल पते.
इस लेसन में दिए गए चरणों में यह माना गया है कि आपके पास, उपयोगकर्ता के चुने गए संपर्क के लिए पहले से ही एक
ContactsContract.Contacts
लाइन मौजूद है.
संपर्क नाम वापस पाना लेसन में बताया गया है कि
संपर्कों की सूची फिर से पाएं.
किसी संपर्क की सारी जानकारी वापस पाएं
किसी संपर्क की पूरी जानकारी पाने के लिए, ContactsContract.Data
टेबल में ऐसी सभी पंक्तियां खोजें जिनमें संपर्क का LOOKUP_KEY
शामिल हो. यह कॉलम यहां उपलब्ध है
ContactsContract.Data
टेबल, क्योंकि Contacts
सेवा देने वाली कंपनी, 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.CommonDataKinds.Email
ContactsContract.Data
क्लास में तय किया गया है. ईमेल-विशिष्ट का उपयोग कर रहा है
कॉलम के नाम से कोड पढ़ने में ज़्यादा आसान हो जाता है.
प्रोजेक्शन में, आप
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 ";