किसी संपर्क की जानकारी वापस पाना

इस लेसन में, किसी संपर्क की ज़्यादा जानकारी वाले डेटा को वापस पाने का तरीका बताया गया है. जैसे, ईमेल पते, फ़ोन नंबर वगैरह. यह वह जानकारी होती है जिसे उपयोगकर्ता किसी संपर्क को खोजते समय देखना चाहते हैं. आपके पास किसी संपर्क की पूरी जानकारी देने या सिर्फ़ किसी खास तरह की जानकारी दिखाने का विकल्प होता है. जैसे, ईमेल पते.

इस लेसन में दिए गए चरणों में यह माना गया है कि आपके पास, उपयोगकर्ता के चुने गए संपर्क के लिए पहले से ही एक 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 ";