संपर्क सूची, Android का एक बेहतरीन और आसानी से इस्तेमाल किया जा सकने वाला कॉम्पोनेंट है. यह डिवाइस की सेंट्रल रिपॉज़िटरी में मौजूद लोगों के डेटा को मैनेज करता है. संपर्क सूची, उस डेटा का सोर्स है जो आपको डिवाइस के संपर्क ऐप्लिकेशन में दिखता है. इसके डेटा को अपने ऐप्लिकेशन में भी ऐक्सेस किया जा सकता है. साथ ही, डिवाइस और ऑनलाइन सेवाओं के बीच डेटा ट्रांसफ़र किया जा सकता है. सेवा देने वाली कंपनी, कई तरह के डेटा सोर्स का इस्तेमाल करती है. साथ ही, हर व्यक्ति के लिए ज़्यादा से ज़्यादा डेटा मैनेज करने की कोशिश करती है. इस वजह से, इसका संगठन जटिल है. इस वजह से, सेवा देने वाली कंपनी के एपीआई में कॉन्ट्रैक्ट क्लास और इंटरफ़ेस का एक बड़ा सेट शामिल होता है. इससे डेटा को वापस पाने और उसमें बदलाव करने, दोनों में मदद मिलती है.
इस गाइड में इनके बारे में बताया गया है:
- सेवा देने वाली कंपनी का बुनियादी स्ट्रक्चर.
- सेवा देने वाली कंपनी से डेटा वापस पाने का तरीका.
- प्रोवाइडर में डेटा में बदलाव करने का तरीका.
- अपने सर्वर से संपर्क सूची में डेटा सिंक करने के लिए, सिंक अडैप्टर लिखने का तरीका.
इस गाइड में यह माना गया है कि आपको Android के कॉन्टेंट देने वाले के बारे में बुनियादी जानकारी है. Android के कॉन्टेंट देने वाले के बारे में ज़्यादा जानने के लिए, कॉन्टेंट देने वाले के बारे में बुनियादी जानकारी गाइड पढ़ें.
संपर्क सूची में मौजूद संगठन
संपर्क सूची, Android का एक कॉम्पोनेंट है जो कॉन्टेंट उपलब्ध कराता है. यह किसी व्यक्ति के बारे में तीन तरह का डेटा सेव करता है. इनमें से हर डेटा, सेवा देने वाली कंपनी की टेबल से जुड़ा होता है. जैसा कि पहली इमेज में दिखाया गया है:
पहली इमेज. संपर्क सूची की टेबल का स्ट्रक्चर.
इन तीनों टेबल को आम तौर पर, उनकी कॉन्ट्रैक्ट क्लास के नाम से जाना जाता है. क्लास, कॉन्टेंट यूआरआई, कॉलम के नाम, और कॉलम की वैल्यू के लिए कॉन्स्टेंट तय करती हैं. इनका इस्तेमाल टेबल करती हैं:
-
ContactsContract.Contactsटेबल - रॉ कॉन्टैक्ट की पंक्तियों के एग्रीगेशन के आधार पर, अलग-अलग लोगों को दिखाने वाली पंक्तियां.
-
ContactsContract.RawContactsटेबल - इन पंक्तियों में किसी व्यक्ति के डेटा की खास जानकारी होती है. यह जानकारी, उपयोगकर्ता खाते और उसके टाइप के हिसाब से होती है.
-
ContactsContract.Dataटेबल - रॉ कॉन्टैक्ट की जानकारी वाली लाइनें, जैसे कि ईमेल पते या फ़ोन नंबर.
ContactsContract में कॉन्ट्रैक्ट क्लास से दिखाई गई अन्य टेबल, सहायक टेबल होती हैं. संपर्क सूची, इनका इस्तेमाल अपने ऑपरेशन मैनेज करने के लिए करती है. इसके अलावा, डिवाइस की संपर्क सूची या टेलीफ़ोनी ऐप्लिकेशन में खास फ़ंक्शन के लिए भी इनका इस्तेमाल किया जाता है.
रॉ कॉन्टैक्ट
रॉ कॉन्टैक्ट, किसी व्यक्ति का ऐसा डेटा होता है जो किसी एक खाता टाइप और खाते के नाम से आता है. संपर्क सूची, किसी व्यक्ति के डेटा के सोर्स के तौर पर एक से ज़्यादा ऑनलाइन सेवाओं को अनुमति देती है. इसलिए, संपर्क सूची में एक ही व्यक्ति के लिए कई रॉ कॉन्टैक्ट हो सकते हैं. एक से ज़्यादा रॉ कॉन्टैक्ट होने पर, उपयोगकर्ता एक ही खाता टाइप के एक से ज़्यादा खातों से किसी व्यक्ति का डेटा जोड़ सकता है.
रॉ कॉन्टैक्ट का ज़्यादातर डेटा, ContactsContract.RawContacts टेबल में सेव नहीं होता. इसके बजाय, इसे ContactsContract.Data टेबल की एक या उससे ज़्यादा पंक्तियों में सेव किया जाता है. डेटा की हर लाइन में एक कॉलम Data.RAW_CONTACT_ID होता है. इसमें पैरंट ContactsContract.RawContacts लाइन की RawContacts._ID वैल्यू होती है.
रॉ कॉन्टैक्ट के अहम कॉलम
ContactsContract.RawContacts टेबल के अहम कॉलम, टेबल 1 में दिए गए हैं. कृपया टेबल के बाद दिए गए नोट पढ़ें:
टेबल 1. रॉ कॉन्टैक्ट के ज़रूरी कॉलम.
| कॉलम का नाम | इस्तेमाल करें | नोट |
|---|---|---|
ACCOUNT_NAME
|
इस रॉ कॉन्टैक्ट के सोर्स के तौर पर इस्तेमाल किए गए खाता टाइप के लिए, खाते का नाम.
उदाहरण के लिए, Google खाते का नाम, डिवाइस के मालिक के Gmail पतों में से एक होता है. ज़्यादा जानकारी के लिए, ACCOUNT_TYPE की अगली एंट्री देखें.
|
इस नाम का फ़ॉर्मैट, खाते के टाइप के हिसाब से तय होता है. यह ज़रूरी नहीं है कि यह कोई ईमेल पता हो. |
ACCOUNT_TYPE
|
खाते का वह टाइप जो इस रॉ कॉन्टैक्ट का सोर्स है. उदाहरण के लिए, Google खाते का टाइप com.google है. अपने खाते के टाइप को हमेशा उस डोमेन के डोमेन आइडेंटिफ़ायर के साथ जोड़ें जिसका मालिकाना हक या कंट्रोल आपके पास है. इससे यह पक्का होगा कि आपके खाते का टाइप यूनीक है.
|
संपर्कों का डेटा उपलब्ध कराने वाले खाता टाइप में, आम तौर पर एक सिंक अडैप्टर जुड़ा होता है. यह अडैप्टर, संपर्क सूची के साथ सिंक होता है. |
DELETED
|
रॉ कॉन्टैक्ट के लिए "मिटाया गया" फ़्लैग. | इस फ़्लैग की मदद से, संपर्क सूची, लाइन को इंटरनल तौर पर तब तक बनाए रख सकती है, जब तक सिंक अडैप्टर अपने सर्वर से लाइन को मिटा नहीं देते. इसके बाद, लाइन को रिपॉज़िटरी से मिटा दिया जाता है. |
नोट
ContactsContract.RawContacts टेबल के बारे में अहम जानकारी यहां दी गई है:
-
रॉ कॉन्टैक्ट का नाम,
ContactsContract.RawContactsमें उसकी लाइन में सेव नहीं किया जाता. इसके बजाय, इसेContactsContract.Dataटेबल में,ContactsContract.CommonDataKinds.StructuredNameलाइन में सेव किया जाता है.ContactsContract.Dataटेबल में, रॉ कॉन्टैक्ट के लिए इस तरह की सिर्फ़ एक लाइन होती है. -
चेतावनी: रॉ कॉन्टैक्ट की लाइन में अपने खाते में मौजूद डेटा इस्तेमाल करने के लिए, उसे पहले
AccountManagerके साथ रजिस्टर करना होगा. इसके लिए, उपयोगकर्ताओं को खातों की सूची में खाते का टाइप और नाम जोड़ने के लिए कहें. अगर ऐसा नहीं किया जाता है, तो संपर्क सूची आपके रॉ कॉन्टैक्ट की लाइन को अपने-आप मिटा देगी.उदाहरण के लिए, मान लें कि आपको अपने ऐप्लिकेशन में,
com.example.dataserviceडोमेन वाली वेब पर आधारित सेवा के लिए संपर्कों का डेटा सेव रखना है. साथ ही, आपकी सेवा के लिए उपयोगकर्ता का खाताbecky.sharp@dataservice.example.comहै. ऐसे में, उपयोगकर्ता को पहले खाते का "टाइप" (com.example.dataservice) और खाते का "नाम" (becky.smart@dataservice.example.com) जोड़ना होगा. इसके बाद ही, आपका ऐप्लिकेशन रॉ कॉन्टैक्ट की लाइनें जोड़ सकता है. दस्तावेज़ में, उपयोगकर्ता को इस ज़रूरी शर्त के बारे में बताया जा सकता है. इसके अलावा, उपयोगकर्ता को टाइप और नाम या दोनों जोड़ने के लिए कहा जा सकता है. खाते के टाइप और खाते के नाम के बारे में ज़्यादा जानकारी, अगले सेक्शन में दी गई है.
रॉ कॉन्टैक्ट डेटा के सोर्स
रॉ कॉन्टैक्ट कैसे काम करते हैं, यह समझने के लिए "Emily Dickinson" नाम की उपयोगकर्ता का उदाहरण लें. उसके डिवाइस पर ये तीन उपयोगकर्ता खाते मौजूद हैं:
emily.dickinson@gmail.comemilyd@gmail.com- Twitter खाता "belle_of_amherst"
इस उपयोगकर्ता ने खाते की सेटिंग में जाकर, इन तीनों खातों के लिए संपर्क सिंक करें सुविधा चालू की है.
मान लें कि Emily Dickinson ने ब्राउज़र विंडो खोली और emily.dickinson@gmail.com के तौर पर Gmail में लॉग इन किया. इसके बाद, उन्होंने Contacts खोला और "Thomas Higginson" को जोड़ा. बाद में, वह emilyd@gmail.com के तौर पर Gmail में लॉग इन करती है और "थॉमस हिगिन्सन" को एक ईमेल भेजती है. इससे, थॉमस हिगिन्सन अपने-आप ही संपर्क के तौर पर जुड़ जाते हैं. वह Twitter पर "colonel_tom" (थॉमस हिगिन्सन का Twitter आईडी) को भी फ़ॉलो करती हैं.
इस काम के नतीजे के तौर पर, संपर्क सूची तीन रॉ कॉन्टैक्ट बनाती है:
-
emily.dickinson@gmail.comसे जुड़े "थॉमस हिगिन्सन" के लिए एक रॉ कॉन्टैक्ट. उपयोगकर्ता खाते का टाइप Google है. -
"Thomas Higginson" के लिए दूसरा रॉ कॉन्टैक्ट, जो
emilyd@gmail.comसे जुड़ा है. उपयोगकर्ता खाते का टाइप भी Google है. यहां एक दूसरा रॉ कॉन्टैक्ट भी है. हालांकि, इसका नाम पिछले नाम से मिलता-जुलता है, क्योंकि इस व्यक्ति को किसी दूसरे उपयोगकर्ता खाते के लिए जोड़ा गया था. - "belle_of_amherst" से जुड़े "Thomas Higginson" के लिए तीसरा रॉ कॉन्टैक्ट. उपयोगकर्ता खाते का टाइप Twitter है.
डेटा
जैसा कि पहले बताया गया है, रॉ कॉन्टैक्ट का डेटा, ContactsContract.Data की उस लाइन में सेव किया जाता है जो रॉ कॉन्टैक्ट की _ID वैल्यू से लिंक होती है. इससे एक ही रॉ कॉन्टैक्ट में, एक ही तरह के डेटा के कई इंस्टेंस हो सकते हैं. जैसे, ईमेल पते या फ़ोन नंबर. उदाहरण के लिए, अगर emilyd@gmail.com के लिए "थॉमस हिगिन्सन" (Google खाते emilyd@gmail.com से जुड़े थॉमस हिगिन्सन के लिए रॉ कॉन्टैक्ट की लाइन) के पास घर का ईमेल पता thigg@gmail.com और ऑफ़िस वाला ईमेल पता thomas.higginson@gmail.com है, तो संपर्क सूची, ईमेल पते की दो लाइनें सेव करती है और दोनों को रॉ कॉन्टैक्ट से लिंक करती है.
ध्यान दें कि इस एक टेबल में अलग-अलग तरह का डेटा सेव किया गया है. डिसप्ले नेम, फ़ोन नंबर, ईमेल पता, डाक पता, फ़ोटो, और वेबसाइट की जानकारी वाली लाइनें, ContactsContract.Data टेबल में मौजूद होती हैं. इसे मैनेज करने के लिए, ContactsContract.Data टेबल में कुछ कॉलम के नाम जानकारी देने वाले हैं,
जबकि कुछ कॉलम के नाम सामान्य हैं. जानकारी देने वाले नाम के कॉलम में मौजूद कॉन्टेंट का मतलब एक ही होता है, भले ही पंक्ति में मौजूद डेटा का टाइप कुछ भी हो. वहीं, सामान्य नाम वाले कॉलम में मौजूद कॉन्टेंट का मतलब, डेटा के टाइप के हिसाब से अलग-अलग होता है.
कॉलम के नाम, जानकारी देने वाले होने चाहिए
जानकारी देने वाले कॉलम के नामों के कुछ उदाहरण यहां दिए गए हैं:
-
RAW_CONTACT_ID -
इस डेटा के लिए, रॉ कॉन्टैक्ट के
_IDकॉलम की वैल्यू. -
MIMETYPE -
इस लाइन में सेव किए गए डेटा का टाइप, जिसे कस्टम एमआईएमई टाइप के तौर पर दिखाया गया है. संपर्क सूची,
ContactsContract.CommonDataKindsकी सबक्लास में तय किए गए एमआईएमई टाइप का इस्तेमाल करती है. ये एमआईएमई टाइप ओपन सोर्स हैं. इनका इस्तेमाल, संपर्क सूची के साथ काम करने वाला कोई भी ऐप्लिकेशन या सिंक अडैप्टर कर सकता है. -
IS_PRIMARY -
अगर किसी रॉ कॉन्टैक्ट के लिए, इस तरह की डेटा लाइन एक से ज़्यादा बार हो सकती है, तो
IS_PRIMARYकॉलम, उस डेटा लाइन को फ़्लैग करता है जिसमें इस तरह का मुख्य डेटा होता है. उदाहरण के लिए, अगर उपयोगकर्ता किसी संपर्क के फ़ोन नंबर को दबाकर रखता है और डिफ़ॉल्ट के तौर पर सेट करें को चुनता है, तो उस नंबर वालीContactsContract.Dataलाइन केIS_PRIMARYकॉलम को शून्य के अलावा किसी दूसरी वैल्यू पर सेट किया जाता है.
कॉलम के सामान्य नाम
DATA1 से लेकर DATA15 तक के नाम वाले 15 सामान्य कॉलम हैं, जो आम तौर पर उपलब्ध होते हैं. साथ ही, SYNC1 से लेकर SYNC4 तक के नाम वाले चार अतिरिक्त सामान्य कॉलम हैं, जिनका इस्तेमाल सिर्फ़ सिंक अडैप्टर को करना चाहिए. कॉलम के नाम के सामान्य कॉन्स्टेंट हमेशा काम करते हैं, भले ही पंक्ति में मौजूद डेटा का टाइप कुछ भी हो.
DATA1 कॉलम को इंडेक्स किया गया है. संपर्क सूची, इस कॉलम का इस्तेमाल हमेशा उस डेटा के लिए करती है जिसके बारे में उसे लगता है कि क्वेरी में उसे सबसे ज़्यादा टारगेट किया जाएगा. उदाहरण के लिए,
ईमेल वाली लाइन में, इस कॉलम में असल ईमेल पता होता है.
कन्वेंशन के मुताबिक, कॉलम DATA15 को बाइनरी लार्ज ऑब्जेक्ट (BLOB) डेटा को सेव करने के लिए रिज़र्व किया गया है. जैसे, फ़ोटो के थंबनेल.
टाइप के हिसाब से कॉलम के नाम
किसी खास तरह की लाइन के कॉलम के साथ काम करना आसान बनाने के लिए, संपर्क सूची
टाइप के हिसाब से कॉलम के नाम के कॉन्स्टेंट भी उपलब्ध कराती है. इन्हें
ContactsContract.CommonDataKinds की सबक्लास में तय किया जाता है. कॉन्स्टेंट, एक ही कॉलम के नाम को अलग-अलग कॉन्स्टेंट नाम देते हैं. इससे आपको किसी खास टाइप की लाइन में मौजूद डेटा को ऐक्सेस करने में मदद मिलती है.
उदाहरण के लिए, ContactsContract.CommonDataKinds.Email क्लास, ContactsContract.Data लाइन के लिए टाइप के हिसाब से कॉलम के नाम के कॉन्स्टेंट तय करती है. इस लाइन का एमआईएमई टाइप Email.CONTENT_ITEM_TYPE है. क्लास में, ईमेल पते वाले कॉलम के लिए कॉन्स्टेंट ADDRESS शामिल है. ADDRESS की असल वैल्यू "data1" है. यह कॉलम के सामान्य नाम के जैसी ही है.
चेतावनी: ContactsContract.Data टेबल में अपना कस्टम डेटा जोड़ने के लिए, ऐसी लाइन का इस्तेमाल न करें जिसमें सेवा देने वाली कंपनी का पहले से तय किया गया एमआईएमई टाइप मौजूद हो. ऐसा करने पर, आपका डेटा मिट सकता है या सेवा देने वाली कंपनी के सिस्टम में गड़बड़ी हो सकती है. उदाहरण के लिए, आपको एमआईएमई टाइप Email.CONTENT_ITEM_TYPE वाली ऐसी लाइन नहीं जोड़नी चाहिए जिसमें DATA1 कॉलम में ईमेल पते के बजाय उपयोगकर्ता नाम शामिल हो. अगर पंक्ति के लिए अपने कस्टम एमआईएमई टाइप का इस्तेमाल किया जाता है, तो आपके पास टाइप के हिसाब से कॉलम के नाम तय करने और कॉलम को अपनी पसंद के मुताबिक इस्तेमाल करने की सुविधा होती है.
दूसरी इमेज में दिखाया गया है कि जानकारी वाले कॉलम और डेटा कॉलम, ContactsContract.Data पंक्ति में कैसे दिखते हैं. साथ ही, यह भी दिखाया गया है कि टाइप के हिसाब से कॉलम के नाम, सामान्य कॉलम के नामों को कैसे "ओवरले" करते हैं
दूसरी इमेज. टाइप के हिसाब से कॉलम के नाम और सामान्य कॉलम के नाम.
टाइप के हिसाब से कॉलम के नाम की क्लास
टेबल 2 में, सबसे ज़्यादा इस्तेमाल किए जाने वाले टाइप-स्पेसिफ़िक कॉलम नेम क्लास की सूची दी गई है:
टेबल 2. टाइप के हिसाब से कॉलम के नाम की क्लास
| मैपिंग क्लास | डेटा का टाइप | नोट |
|---|---|---|
ContactsContract.CommonDataKinds.StructuredName |
इस डेटा लाइन से जुड़े रॉ कॉन्टैक्ट के नाम का डेटा. | रॉ कॉन्टैक्ट में इनमें से सिर्फ़ एक लाइन होती है. |
ContactsContract.CommonDataKinds.Photo |
डेटा की इस लाइन से जुड़े रॉ कॉन्टैक्ट की मुख्य फ़ोटो. | रॉ कॉन्टैक्ट में इनमें से सिर्फ़ एक लाइन होती है. |
ContactsContract.CommonDataKinds.Email |
डेटा की इस लाइन से जुड़े रॉ कॉन्टैक्ट का ईमेल पता. | किसी रॉ कॉन्टैक्ट में कई ईमेल पते हो सकते हैं. |
ContactsContract.CommonDataKinds.StructuredPostal |
इस डेटा लाइन से जुड़े रॉ कॉन्टैक्ट का डाक पता. | किसी रॉ कॉन्टैक्ट के कई डाक पते हो सकते हैं. |
ContactsContract.CommonDataKinds.GroupMembership |
एक आइडेंटिफ़ायर, जो रॉ कॉन्टैक्ट को संपर्क सूची में मौजूद किसी ग्रुप से लिंक करता है. | ग्रुप, खाता टाइप और खाते के नाम की एक वैकल्पिक सुविधा है. इनके बारे में ज़्यादा जानकारी, संपर्क ग्रुप सेक्शन में दी गई है. |
संपर्क
संपर्क सूची, सभी खाता टाइप और खातों के नामों की रॉ कॉन्टैक्ट वाली पंक्तियों को जोड़कर, एक संपर्क बनाती है. इससे, किसी व्यक्ति के लिए उपयोगकर्ता के इकट्ठा किए गए सभी डेटा को दिखाने और उसमें बदलाव करने में मदद मिलती है. संपर्क सूची, नए संपर्क की पंक्तियां बनाने और रॉ कॉन्टैक्ट को किसी मौजूदा संपर्क की पंक्ति के साथ जोड़ने की प्रोसेस को मैनेज करती है. ऐप्लिकेशन और सिंक अडैप्टर, दोनों को संपर्क जोड़ने की अनुमति नहीं है. साथ ही, संपर्क की लाइन में मौजूद कुछ कॉलम सिर्फ़ पढ़ने के लिए हैं.
ध्यान दें: अगर insert() का इस्तेमाल करके, संपर्क सूची में कोई संपर्क जोड़ने की कोशिश की जाती है, तो आपको UnsupportedOperationException अपवाद मिलेगा. अगर "सिर्फ़ पढ़ने के लिए" के तौर पर लिस्ट किए गए कॉलम को अपडेट करने की कोशिश की जाती है, तो अपडेट को अनदेखा कर दिया जाता है.
संपर्क सूची, नया रॉ कॉन्टैक्ट जोड़े जाने पर एक नया संपर्क बनाती है. यह संपर्क, किसी भी मौजूदा संपर्क से मेल नहीं खाता. अगर किसी मौजूदा रॉ कॉन्टैक्ट का डेटा इस तरह बदल जाता है कि वह अब उस संपर्क से मेल नहीं खाता जिससे वह पहले जुड़ा था, तो सेवा देने वाली कंपनी भी ऐसा करती है. अगर कोई ऐप्लिकेशन या सिंक अडैप्टर, नया रॉ कॉन्टैक्ट बनाता है और वह किसी मौजूदा संपर्क से मैच करता है, तो नए रॉ कॉन्टैक्ट को मौजूदा संपर्क में जोड़ दिया जाता है.
संपर्क सूची, संपर्क की पंक्ति को उसकी रॉ कॉन्टैक्ट की पंक्तियों से लिंक करती है. इसके लिए, वह Contacts टेबल में संपर्क की पंक्ति के _ID कॉलम का इस्तेमाल करती है. रॉ कॉन्टैक्ट टेबल के CONTACT_ID कॉलम
ContactsContract.RawContacts में, हर रॉ कॉन्टैक्ट लाइन से जुड़ी कॉन्टैक्ट लाइन के लिए,
_ID वैल्यू होती हैं.
ContactsContract.Contacts टेबल में LOOKUP_KEY कॉलम भी होता है. यह संपर्क वाली पंक्ति का "स्थायी" लिंक होता है. संपर्क सूची, संपर्कों को अपने-आप मैनेज करती है. इसलिए, यह एग्रीगेशन या सिंक करने की प्रोसेस के दौरान, संपर्क की लाइन में मौजूद _ID वैल्यू को बदल सकती है. अगर ऐसा होता है, तो भी कॉन्टेंट यूआरआई
CONTENT_LOOKUP_URI को संपर्क के LOOKUP_KEY के साथ जोड़ने पर,
यह संपर्क की लाइन पर ले जाएगा. इसलिए,
LOOKUP_KEY
का इस्तेमाल करके, "पसंदीदा" संपर्कों के लिंक बनाए रखे जा सकते हैं. इस कॉलम का अपना फ़ॉर्मैट होता है, जो _ID कॉलम के फ़ॉर्मैट से अलग होता है.
तीसरी इमेज में दिखाया गया है कि तीनों मुख्य टेबल एक-दूसरे से कैसे जुड़ी हैं.
तीसरी इमेज. संपर्क, रॉ कॉन्टैक्ट, और जानकारी वाली टेबल के बीच संबंध.
चेतावनी: अगर आपने Google Play Store पर अपना ऐप्लिकेशन पब्लिश किया है या आपका ऐप्लिकेशन Android 10 (एपीआई लेवल 29) या इसके बाद के वर्शन वाले डिवाइस पर मौजूद है, तो ध्यान रखें कि संपर्क डेटा फ़ील्ड और तरीकों का एक सीमित सेट अब काम नहीं करता.
यहां बताई गई शर्तों के तहत, सिस्टम समय-समय पर इन डेटा फ़ील्ड में लिखी गई किसी भी वैल्यू को मिटा देता है:
-
ContactsContract.ContactOptionsColumns.LAST_TIME_CONTACTED -
ContactsContract.ContactOptionsColumns.TIMES_CONTACTED -
ContactsContract.DataUsageStatColumns.LAST_TIME_USED -
ContactsContract.DataUsageStatColumns.TIMES_USED
ऊपर दिए गए डेटा फ़ील्ड को सेट करने के लिए इस्तेमाल किए जाने वाले एपीआई भी अब काम नहीं करते:
इसके अलावा, इन फ़ील्ड में अब अक्सर इस्तेमाल किए जाने वाले संपर्क नहीं दिखते. ध्यान दें कि इनमें से कुछ फ़ील्ड, संपर्कों की रैंकिंग पर सिर्फ़ तब असर डालते हैं, जब संपर्क किसी खास डेटा टाइप का हिस्सा हों.
-
ContactsContract.Contacts.CONTENT_FREQUENT_URI -
ContactsContract.Contacts.CONTENT_STREQUENT_URI -
ContactsContract.Contacts.CONTENT_STREQUENT_FILTER_URI -
CONTENT_FILTER_URI(सिर्फ़ ईमेल, फ़ोन, कॉल किए जा सकने वाले, और संपर्क किए जा सकने वाले डेटा टाइप पर असर डालता है) -
ENTERPRISE_CONTENT_FILTER_URI(इसका असर सिर्फ़ ईमेल, फ़ोन, और कॉल किए जा सकने वाले डेटा टाइप पर पड़ता है)
अगर आपके ऐप्लिकेशन इन फ़ील्ड या एपीआई को ऐक्सेस या अपडेट कर रहे हैं, तो अन्य तरीकों का इस्तेमाल करें. उदाहरण के लिए, निजी कॉन्टेंट देने वाले या आपके ऐप्लिकेशन या बैकएंड सिस्टम में सेव किए गए अन्य डेटा का इस्तेमाल करके, कुछ मामलों में ज़रूरतें पूरी की जा सकती हैं.
यह पुष्टि करने के लिए कि इस बदलाव से आपके ऐप्लिकेशन की मुख्य सुविधाओं पर कोई असर नहीं पड़ा है, इन डेटा फ़ील्ड को मैन्युअल तरीके से मिटाया जा सकता है. इसके लिए, Android 4.1 (एपीआई लेवल 16) या इसके बाद के वर्शन वाले डिवाइस पर, यह एडीबी कमांड चलाएं:
adb shell content delete \ --uri content://com.android.contacts/contacts/delete_usage
सिंक अडैप्टर से मिला डेटा
उपयोगकर्ता, डिवाइस में सीधे तौर पर संपर्कों का डेटा डालते हैं. हालांकि, डेटा सिंक अडैप्टर की मदद से, वेब सेवाओं से संपर्क सूची में भी जाता है. इससे डिवाइस और सेवाओं के बीच डेटा अपने-आप ट्रांसफ़र होता है. सिंक अडैप्टर, सिस्टम के कंट्रोल में बैकग्राउंड में चलते हैं. साथ ही, वे डेटा को मैनेज करने के लिए ContentResolver मेथड को कॉल करते हैं.
Android में, सिंक अडैप्टर जिस वेब सेवा के साथ काम करता है उसकी पहचान खाता टाइप से की जाती है. हर सिंक अडैप्टर, एक ही तरह के खाते के साथ काम करता है. हालांकि, यह उस तरह के खाते के लिए कई खातों के नाम के साथ काम कर सकता है. खाते के टाइप और खाते के नाम के बारे में, रॉ कॉन्टैक्ट के डेटा के सोर्स सेक्शन में कम शब्दों में बताया गया है. यहां दी गई परिभाषाओं में ज़्यादा जानकारी दी गई है. साथ ही, यह बताया गया है कि खाते का टाइप और नाम, सिंक अडैप्टर और सेवाओं से कैसे जुड़े हैं.
- खाता टाइप
-
उस सेवा की पहचान करता है जिसमें उपयोगकर्ता ने डेटा सेव किया है. ज़्यादातर मामलों में, उपयोगकर्ता को सेवा देने वाली कंपनी के साथ अपनी पहचान की पुष्टि करनी होती है. उदाहरण के लिए, Google Contacts एक खाता टाइप है, जिसकी पहचान
google.comकोड से की जाती है. यह वैल्यू,AccountManagerके इस्तेमाल किए गए खाता टाइप से मेल खाती है. - खाते का नाम
- किसी खाते के टाइप के लिए, किसी खास खाते या लॉगिन की पहचान करता है. Google Contacts खाते, Google खातों की तरह ही होते हैं. इनमें खाते के नाम के तौर पर ईमेल पता होता है. अन्य सेवाएं, एक शब्द वाले उपयोगकर्ता नाम या अंकों वाले आईडी का इस्तेमाल कर सकती हैं.
खाते के टाइप यूनीक होने ज़रूरी नहीं हैं. कोई उपयोगकर्ता, Google Contacts के कई खाते कॉन्फ़िगर कर सकता है और उनका डेटा, संपर्क सूची में डाउनलोड कर सकता है. ऐसा तब हो सकता है, जब उपयोगकर्ता के पास निजी खाते के नाम के लिए निजी संपर्कों का एक सेट हो और काम के लिए दूसरा सेट हो. खाते के नाम आम तौर पर यूनीक होते हैं. ये दोनों मिलकर, संपर्क सूची और किसी बाहरी सेवा के बीच डेटा फ़्लो की पहचान करते हैं.
अगर आपको अपनी सेवा का डेटा, संपर्क सूची में ट्रांसफ़र करना है, तो आपको अपना सिंक अडैप्टर लिखना होगा. इस बारे में ज़्यादा जानकारी, संपर्क सूची के सिंक अडैप्टर सेक्शन में दी गई है.
चौथी इमेज में दिखाया गया है कि संपर्क सूची, लोगों के डेटा के फ़्लो में कैसे फ़िट होती है. "सिंक अडैप्टर" के तौर पर मार्क किए गए बॉक्स में, हर अडैप्टर को उसके खाता टाइप के हिसाब से लेबल किया जाता है.
चौथी इमेज. संपर्क सूची में डेटा का फ़्लो.
ज़रूरी अनुमतियां
संपर्क सूची को ऐक्सेस करने के लिए, ऐप्लिकेशन को इन अनुमतियों का अनुरोध करना होगा:
- एक या उससे ज़्यादा टेबल को पढ़ने का ऐक्सेस
-
READ_CONTACTS, जिसेAndroidManifest.xmlमें<uses-permission>एलिमेंट के साथ<uses-permission android:name="android.permission.READ_CONTACTS">के तौर पर बताया गया है. - एक या उससे ज़्यादा टेबल में डेटा डालने का ऐक्सेस
-
WRITE_CONTACTS, जिसेAndroidManifest.xmlमें<uses-permission>एलिमेंट के साथ<uses-permission android:name="android.permission.WRITE_CONTACTS">के तौर पर बताया गया है.
ये अनुमतियां, उपयोगकर्ता की प्रोफ़ाइल के डेटा पर लागू नहीं होती हैं. उपयोगकर्ता की प्रोफ़ाइल और उसके लिए ज़रूरी अनुमतियों के बारे में, उपयोगकर्ता की प्रोफ़ाइल सेक्शन में बताया गया है.
याद रखें कि उपयोगकर्ता के संपर्कों का डेटा निजी और संवेदनशील होता है. उपयोगकर्ताओं को अपनी निजता की चिंता होती है. इसलिए, वे नहीं चाहते कि ऐप्लिकेशन उनके या उनके संपर्कों के बारे में डेटा इकट्ठा करें. अगर यह साफ़ तौर पर नहीं बताया गया है कि आपको उनके संपर्कों के डेटा को ऐक्सेस करने की अनुमति क्यों चाहिए, तो हो सकता है कि वे आपके ऐप्लिकेशन को कम रेटिंग दें या उसे इंस्टॉल करने से मना कर दें.
उपयोगकर्ता की प्रोफ़ाइल
ContactsContract.Contacts टेबल में एक लाइन होती है. इसमें डिवाइस के उपयोगकर्ता की प्रोफ़ाइल का डेटा होता है. इस डेटा से, उपयोगकर्ता के किसी संपर्क के बजाय, डिवाइस के user के बारे में जानकारी मिलती है. प्रोफ़ाइल का इस्तेमाल करने वाले हर सिस्टम के लिए, प्रोफ़ाइल कॉन्टैक्ट की लाइन को रॉ कॉन्टैक्ट की लाइन से लिंक किया जाता है.
प्रोफ़ाइल के रॉ कॉन्टैक्ट की हर पंक्ति में, डेटा की कई पंक्तियां हो सकती हैं. उपयोगकर्ता की प्रोफ़ाइल को ऐक्सेस करने के लिए, कॉन्सटैंट ContactsContract.Profile क्लास में उपलब्ध हैं.
उपयोगकर्ता की प्रोफ़ाइल को ऐक्सेस करने के लिए, खास अनुमतियों की ज़रूरत होती है. पढ़ने और लिखने के लिए ज़रूरी READ_CONTACTS और WRITE_CONTACTS अनुमतियों के अलावा, उपयोगकर्ता की प्रोफ़ाइल को ऐक्सेस करने के लिए, पढ़ने और लिखने के ऐक्सेस के लिए, android.Manifest.permission#READ_PROFILE और android.Manifest.permission#WRITE_PROFILE अनुमतियों की ज़रूरत होती है.
ध्यान रखें कि आपको उपयोगकर्ता की प्रोफ़ाइल को संवेदनशील मानना चाहिए. अनुमति android.Manifest.permission#READ_PROFILE की मदद से, डिवाइस के उपयोगकर्ता की पहचान ज़ाहिर करने वाला डेटा ऐक्सेस किया जा सकता है. अपने ऐप्लिकेशन के ब्यौरे में, उपयोगकर्ता को यह ज़रूर बताएं कि आपको उपयोगकर्ता की प्रोफ़ाइल ऐक्सेस करने की अनुमतियां क्यों चाहिए.
उपयोगकर्ता की प्रोफ़ाइल वाली संपर्क लाइन को वापस पाने के लिए, ContentResolver.query() को कॉल करें. कॉन्टेंट यूआरआई को
CONTENT_URI पर सेट करें और चुनने की कोई शर्त न दें. इस कॉन्टेंट यूआरआई का इस्तेमाल, प्रोफ़ाइल के लिए रॉ कॉन्टैक्ट या डेटा पाने के लिए, बेस यूआरआई के तौर पर भी किया जा सकता है. उदाहरण के लिए, यह स्निपेट प्रोफ़ाइल का डेटा हासिल करता है:
Kotlin
// Sets the columns to retrieve for the user profile projection = arrayOf( ContactsContract.Profile._ID, ContactsContract.Profile.DISPLAY_NAME_PRIMARY, ContactsContract.Profile.LOOKUP_KEY, ContactsContract.Profile.PHOTO_THUMBNAIL_URI ) // Retrieves the profile from the Contacts Provider profileCursor = contentResolver.query( ContactsContract.Profile.CONTENT_URI, projection, null, null, null )
Java
// Sets the columns to retrieve for the user profile projection = new String[] { Profile._ID, Profile.DISPLAY_NAME_PRIMARY, Profile.LOOKUP_KEY, Profile.PHOTO_THUMBNAIL_URI }; // Retrieves the profile from the Contacts Provider profileCursor = getContentResolver().query( Profile.CONTENT_URI, projection , null, null, null);
ध्यान दें: अगर आपको संपर्क की कई लाइनें मिलती हैं और आपको यह तय करना है कि उनमें से कोई एक उपयोगकर्ता की प्रोफ़ाइल है या नहीं, तो लाइन के IS_USER_PROFILE कॉलम की जांच करें. अगर संपर्क, उपयोगकर्ता की प्रोफ़ाइल है, तो इस कॉलम को "1" पर सेट किया जाता है.
संपर्क सूची का मेटाडेटा
संपर्क सूची, डेटा को मैनेज करती है. इससे रिपॉज़िटरी में मौजूद संपर्कों के डेटा की स्थिति को ट्रैक किया जाता है. रिपॉज़िटरी का यह मेटाडेटा, अलग-अलग जगहों पर सेव किया जाता है. इनमें रॉ कॉन्टैक्ट, डेटा, और कॉन्टैक्ट टेबल की लाइनें, ContactsContract.Settings टेबल, और ContactsContract.SyncState टेबल शामिल हैं. नीचे दी गई टेबल में, इनमें से हर मेटाडेटा का असर दिखाया गया है:
टेबल 3. संपर्क सूची में मौजूद मेटाडेटा
| टेबल | कॉलम | वैल्यू | मतलब |
|---|---|---|---|
ContactsContract.RawContacts |
DIRTY |
"0" - पिछली बार सिंक किए जाने के बाद से कोई बदलाव नहीं किया गया है. |
यह उन रॉ कॉन्टैक्ट को मार्क करता है जिन्हें डिवाइस पर बदला गया था और जिन्हें सर्वर पर वापस सिंक करना है. जब Android ऐप्लिकेशन किसी पंक्ति को अपडेट करते हैं, तो संपर्क सूची इस वैल्यू को अपने-आप सेट करती है.
रॉ कॉन्टैक्ट या डेटा टेबल में बदलाव करने वाले सिंक अडैप्टर को, इस्तेमाल किए जाने वाले कॉन्टेंट यूआरआई में हमेशा स्ट्रिंग |
| "1" - पिछली बार सिंक करने के बाद से बदलाव किया गया है. इसे सर्वर पर फिर से सिंक करना होगा. | |||
ContactsContract.RawContacts |
VERSION |
इस लाइन का वर्शन नंबर. | जब भी पंक्ति या उससे जुड़े डेटा में बदलाव होता है, तो संपर्क सूची इस वैल्यू को अपने-आप बढ़ा देती है. |
ContactsContract.Data |
DATA_VERSION |
इस पंक्ति का वर्शन नंबर. | जब भी डेटा की लाइन में बदलाव किया जाता है, तब संपर्क सूची इस वैल्यू को अपने-आप बढ़ा देती है. |
ContactsContract.RawContacts |
SOURCE_ID |
स्ट्रिंग वैल्यू, जिससे इस रॉ कॉन्टैक्ट की पहचान उस खाते में की जाती है जिसमें इसे बनाया गया था. |
जब कोई सिंक अडैप्टर नया रॉ कॉन्टैक्ट बनाता है, तो इस कॉलम को रॉ कॉन्टैक्ट के लिए सर्वर के यूनीक आईडी पर सेट किया जाना चाहिए. जब कोई Android ऐप्लिकेशन नया रॉ कॉन्टैक्ट बनाता है, तो ऐप्लिकेशन को इस कॉलम को खाली छोड़ देना चाहिए. इससे सिंक अडैप्टर को सिग्नल मिलता है कि उसे सर्वर पर एक नया रॉ कॉन्टैक्ट बनाना चाहिए और SOURCE_ID के लिए वैल्यू हासिल करनी चाहिए.
खास तौर पर, हर खाता टाइप के लिए सोर्स आईडी यूनीक होना चाहिए. साथ ही, सिंक करने के दौरान यह आईडी नहीं बदलना चाहिए:
|
ContactsContract.Groups |
GROUP_VISIBLE |
"0" - इस ग्रुप में मौजूद संपर्क, Android ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) में नहीं दिखने चाहिए. | यह कॉलम, उन सर्वर के साथ काम करने के लिए है जो उपयोगकर्ता को कुछ ग्रुप में संपर्कों को छिपाने की अनुमति देते हैं. |
| "1" - इस ग्रुप में मौजूद संपर्कों को ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) में दिखने की अनुमति है. | |||
ContactsContract.Settings |
UNGROUPED_VISIBLE |
"0" - इस खाते और खाता टाइप के लिए, जो संपर्क किसी ग्रुप से नहीं जुड़े हैं वे Android ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) को नहीं दिखते. |
डिफ़ॉल्ट रूप से, संपर्क तब तक नहीं दिखते, जब तक उनका कोई भी रॉ कॉन्टैक्ट किसी ग्रुप से न जुड़ा हो.
रॉ कॉन्टैक्ट के लिए ग्रुप की सदस्यता, ContactsContract.Data टेबल में एक या उससे ज़्यादा
ContactsContract.CommonDataKinds.GroupMembership पंक्तियों
से दिखती है.
खाते के टाइप और खाते के लिए, ContactsContract.Settings टेबल की लाइन में यह फ़्लैग सेट करके, बिना ग्रुप वाले संपर्कों को दिखने के लिए मजबूर किया जा सकता है.
इस फ़्लैग का इस्तेमाल, उन सर्वर से संपर्क दिखाने के लिए किया जाता है जो ग्रुप का इस्तेमाल नहीं करते.
|
| "1" - इस खाते और खाता टाइप के लिए, ऐसे संपर्क जो किसी ग्रुप से नहीं जुड़े हैं वे ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) को दिखते हैं. | |||
ContactsContract.SyncState |
(सभी) | अपने सिंक अडैप्टर का मेटाडेटा सेव करने के लिए, इस टेबल का इस्तेमाल करें. | इस टेबल की मदद से, सिंक की स्थिति और सिंक से जुड़ा अन्य डेटा, डिवाइस पर हमेशा के लिए सेव किया जा सकता है. |
संपर्क सूची का ऐक्सेस
इस सेक्शन में, संपर्क सूची से डेटा ऐक्सेस करने के दिशा-निर्देशों के बारे में बताया गया है. इसमें इन बातों पर फ़ोकस किया गया है:
- इकाई से जुड़ी क्वेरी.
- एक साथ कई बदलाव करना.
- इंटेंट की मदद से, डेटा को वापस पाना और उसमें बदलाव करना.
- डेटा का रखरखाव.
सिंक अडैप्टर से बदलाव करने के बारे में, संपर्क सूची के सिंक अडैप्टर सेक्शन में ज़्यादा जानकारी दी गई है.
इकाइयों के लिए क्वेरी करना
संपर्क सूची की टेबल को हैरारकी में व्यवस्थित किया जाता है. इसलिए, किसी लाइन और उससे जुड़ी सभी "चाइल्ड" लाइनों को वापस पाना अक्सर मददगार होता है. उदाहरण के लिए, किसी व्यक्ति की पूरी जानकारी दिखाने के लिए, आपको किसी एक ContactsContract.Contacts लाइन के लिए सभी ContactsContract.RawContacts लाइनें या किसी एक ContactsContract.RawContacts लाइन के लिए सभी ContactsContract.CommonDataKinds.Email लाइनें वापस लानी पड़ सकती हैं. इसके लिए, संपर्क सूची एंटिटी कंस्ट्रक्ट उपलब्ध कराती है. ये टेबल के बीच डेटाबेस जॉइन की तरह काम करते हैं.
इकाई, पैरंट टेबल और उसकी चाइल्ड टेबल से चुने गए कॉलम से बनी टेबल की तरह होती है.
किसी इकाई के बारे में क्वेरी करने पर, आपको इकाई में उपलब्ध कॉलम के आधार पर, प्रोजेक्शन और खोज की शर्तें देनी होती हैं. नतीजे के तौर पर, एक Cursor मिलता है. इसमें, चाइल्ड टेबल की हर पंक्ति के लिए एक पंक्ति होती है. उदाहरण के लिए, अगर आपने किसी संपर्क के नाम के लिए ContactsContract.Contacts.Entity और उस नाम के सभी रॉ कॉन्टैक्ट के लिए सभी ContactsContract.CommonDataKinds.Email पंक्तियों की क्वेरी की है, तो आपको हर ContactsContract.CommonDataKinds.Email पंक्ति के लिए एक पंक्ति वाला Cursor वापस मिलेगा.
इकाइयां, क्वेरी को आसान बनाती हैं. एंटिटी का इस्तेमाल करके, किसी संपर्क या रॉ कॉन्टैक्ट के लिए, सभी संपर्कों का डेटा एक साथ वापस पाया जा सकता है. इसके लिए, आपको आईडी पाने के लिए पहले पैरंट टेबल से क्वेरी करने की ज़रूरत नहीं है. इसके बाद, उस आईडी के साथ चाइल्ड टेबल से क्वेरी करने की ज़रूरत नहीं है. साथ ही, संपर्क सूची, एक ही लेन-देन में किसी इकाई के लिए क्वेरी को प्रोसेस करती है. इससे यह पक्का होता है कि वापस पाया गया डेटा, अंदरूनी तौर पर एक जैसा हो.
ध्यान दें: आम तौर पर, किसी इकाई में पैरंट और चाइल्ड टेबल के सभी कॉलम शामिल नहीं होते. अगर आपने किसी ऐसे कॉलम के नाम का इस्तेमाल करने की कोशिश की जो इकाई के लिए कॉलम के नाम के कॉन्सटैंट की सूची में नहीं है, तो आपको Exception मिलेगा.
यहां दिए गए स्निपेट में, किसी संपर्क के लिए सभी रॉ कॉन्टैक्ट की पंक्तियां वापस पाने का तरीका बताया गया है. यह स्निपेट,
एक बड़े ऐप्लिकेशन का हिस्सा है. इसमें दो गतिविधियां हैं, "मुख्य" और "जानकारी". मुख्य गतिविधि, संपर्क की पंक्तियों की सूची दिखाती है. जब उपयोगकर्ता किसी पंक्ति को चुनता है, तो गतिविधि उसका आईडी, ज़्यादा जानकारी वाली गतिविधि को भेजती है. जानकारी वाली गतिविधि, ContactsContract.Contacts.Entity का इस्तेमाल करती है, ताकि चुने गए संपर्क से जुड़े सभी रॉ कॉन्टैक्ट की डेटा वाली सभी लाइनें दिखाई जा सकें.
यह स्निपेट, "जानकारी" गतिविधि से लिया गया है:
Kotlin
... /* * Appends the entity path to the URI. In the case of the Contacts Provider, the * expected URI is content://com.google.contacts/#/entity (# is the ID value). */ contactUri = Uri.withAppendedPath( contactUri, ContactsContract.Contacts.Entity.CONTENT_DIRECTORY ) // Initializes the loader identified by LOADER_ID. loaderManager.initLoader( LOADER_ID, // The identifier of the loader to initialize null, // Arguments for the loader (in this case, none) this // The context of the activity ) // Creates a new cursor adapter to attach to the list view cursorAdapter = SimpleCursorAdapter( this, // the context of the activity R.layout.detail_list_item, // the view item containing the detail widgets mCursor, // the backing cursor fromColumns, // the columns in the cursor that provide the data toViews, // the views in the view item that display the data 0) // flags // Sets the ListView's backing adapter. rawContactList.adapter = cursorAdapter ... override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> { /* * Sets the columns to retrieve. * RAW_CONTACT_ID is included to identify the raw contact associated with the data row. * DATA1 contains the first column in the data row (usually the most important one). * MIMETYPE indicates the type of data in the data row. */ val projection: Array<String> = arrayOf( ContactsContract.Contacts.Entity.RAW_CONTACT_ID, ContactsContract.Contacts.Entity.DATA1, ContactsContract.Contacts.Entity.MIMETYPE ) /* * Sorts the retrieved cursor by raw contact id, to keep all data rows for a single raw * contact collated together. */ val sortOrder = "${ContactsContract.Contacts.Entity.RAW_CONTACT_ID} ASC" /* * Returns a new CursorLoader. The arguments are similar to * ContentResolver.query(), except for the Context argument, which supplies the location of * the ContentResolver to use. */ return CursorLoader( applicationContext, // The activity's context contactUri, // The entity content URI for a single contact projection, // The columns to retrieve null, // Retrieve all the raw contacts and their data rows. null, // sortOrder // Sort by the raw contact ID. ) }
Java
... /* * Appends the entity path to the URI. In the case of the Contacts Provider, the * expected URI is content://com.google.contacts/#/entity (# is the ID value). */ contactUri = Uri.withAppendedPath( contactUri, ContactsContract.Contacts.Entity.CONTENT_DIRECTORY); // Initializes the loader identified by LOADER_ID. getLoaderManager().initLoader( LOADER_ID, // The identifier of the loader to initialize null, // Arguments for the loader (in this case, none) this); // The context of the activity // Creates a new cursor adapter to attach to the list view cursorAdapter = new SimpleCursorAdapter( this, // the context of the activity R.layout.detail_list_item, // the view item containing the detail widgets mCursor, // the backing cursor fromColumns, // the columns in the cursor that provide the data toViews, // the views in the view item that display the data 0); // flags // Sets the ListView's backing adapter. rawContactList.setAdapter(cursorAdapter); ... @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { /* * Sets the columns to retrieve. * RAW_CONTACT_ID is included to identify the raw contact associated with the data row. * DATA1 contains the first column in the data row (usually the most important one). * MIMETYPE indicates the type of data in the data row. */ String[] projection = { ContactsContract.Contacts.Entity.RAW_CONTACT_ID, ContactsContract.Contacts.Entity.DATA1, ContactsContract.Contacts.Entity.MIMETYPE }; /* * Sorts the retrieved cursor by raw contact id, to keep all data rows for a single raw * contact collated together. */ String sortOrder = ContactsContract.Contacts.Entity.RAW_CONTACT_ID + " ASC"; /* * Returns a new CursorLoader. The arguments are similar to * ContentResolver.query(), except for the Context argument, which supplies the location of * the ContentResolver to use. */ return new CursorLoader( getApplicationContext(), // The activity's context contactUri, // The entity content URI for a single contact projection, // The columns to retrieve null, // Retrieve all the raw contacts and their data rows. null, // sortOrder); // Sort by the raw contact ID. }
लोड पूरा होने पर, LoaderManager, onLoadFinished() को कॉलबैक करता है. इस तरीके में, क्वेरी के नतीजों के साथ Cursor को आर्ग्युमेंट के तौर पर पास किया जाता है. अपने ऐप्लिकेशन में, इस Cursor से डेटा हासिल किया जा सकता है, ताकि उसे दिखाया जा सके या उस पर आगे काम किया जा सके.
एक साथ कई बदलाव करना
जब भी संभव हो, आपको संपर्क सूची में डेटा को "बैच मोड" में डालना, अपडेट करना, और मिटाना चाहिए. इसके लिए, ContentProviderOperation ऑब्जेक्ट का ArrayList बनाएं और applyBatch() को कॉल करें. संपर्क सूची, एक ही लेन-देन में applyBatch() के सभी ऑपरेशन करती है. इसलिए, आपके बदलावों से संपर्क सूची में कभी भी कोई गड़बड़ी नहीं होगी. एक साथ कई बदलाव करने की सुविधा से, रॉ कॉन्टैक्ट और उसकी पूरी जानकारी को एक साथ डाला जा सकता है.
ध्यान दें: एक रॉ कॉन्टैक्ट में बदलाव करने के लिए, अपने ऐप्लिकेशन में बदलाव करने के बजाय, डिवाइस के संपर्क ऐप्लिकेशन पर इंटेंट भेजने के बारे में सोचें. ऐसा करने के बारे में, इंटेंट की मदद से डेटा वापस पाना और उसमें बदलाव करना सेक्शन में ज़्यादा जानकारी दी गई है.
यील्ड पॉइंट
एक साथ कई बदलाव करने पर, अन्य प्रोसेस ब्लॉक हो सकती हैं. इससे उपयोगकर्ता को खराब अनुभव मिल सकता है. आपको जो भी बदलाव करने हैं उन्हें कम से कम अलग-अलग सूचियों में व्यवस्थित करने और उन्हें सिस्टम को ब्लॉक करने से रोकने के लिए, आपको एक या उससे ज़्यादा कार्रवाइयों के लिए यील्ड पॉइंट सेट करने चाहिए.
यील्ड पॉइंट एक ContentProviderOperation ऑब्जेक्ट होता है, जिसकी isYieldAllowed() वैल्यू true पर सेट होती है. जब संपर्क सूची को कोई यील्ड पॉइंट मिलता है, तो वह अपना काम रोक देती है, ताकि अन्य प्रोसेस चल सकें. साथ ही, वह मौजूदा लेन-देन को बंद कर देती है. जब प्रोवाइडर फिर से शुरू होता है, तो वह ArrayList में अगले ऑपरेशन के साथ जारी रहता है और एक नया लेन-देन शुरू करता है.
यील्ड पॉइंट की वजह से, applyBatch() को किए गए हर कॉल के लिए एक से ज़्यादा लेन-देन होते हैं. इस वजह से, आपको मिलती-जुलती पंक्तियों के सेट के लिए, आखिरी कार्रवाई के लिए यील्ड पॉइंट सेट करना चाहिए.
उदाहरण के लिए, आपको सेट में आखिरी कार्रवाई के लिए यील्ड पॉइंट सेट करना चाहिए. यह सेट, रॉ कॉन्टैक्ट की पंक्तियों और उनसे जुड़ी डेटा पंक्तियों को जोड़ता है. इसके अलावा, किसी एक संपर्क से जुड़ी पंक्तियों के सेट के लिए आखिरी कार्रवाई के लिए यील्ड पॉइंट सेट करना चाहिए.
यील्ड पॉइंट, ऐटॉमिक ऑपरेशन की एक यूनिट भी होते हैं. दो यील्ड पॉइंट के बीच के सभी ऐक्सेस, एक यूनिट के तौर पर या तो सफल होंगे या असफल. अगर कोई यील्ड पॉइंट सेट नहीं किया जाता है, तो सबसे छोटा ऐटॉमिक ऑपरेशन, ऑपरेशन का पूरा बैच होता है. यील्ड पॉइंट का इस्तेमाल करने पर, सिस्टम की परफ़ॉर्मेंस को खराब होने से बचाया जा सकता है. साथ ही, यह पक्का किया जा सकता है कि ऑपरेशन का सबसेट ऐटॉमिक हो.
बदलाव के लिए बैक रेफ़रंस
जब ContentProviderOperation ऑब्जेक्ट के सेट के तौर पर, कोई नई रॉ कॉन्टैक्ट लाइन और उससे जुड़ी डेटा लाइनें डाली जाती हैं, तो आपको डेटा लाइनों को रॉ कॉन्टैक्ट लाइन से लिंक करना होगा. इसके लिए, रॉ कॉन्टैक्ट की _ID वैल्यू को RAW_CONTACT_ID वैल्यू के तौर पर डालें. हालांकि, डेटा लाइन के लिए ContentProviderOperation बनाते समय यह वैल्यू उपलब्ध नहीं होती. इसकी वजह यह है कि आपने रॉ कॉन्टैक्ट लाइन के लिए, अब तक ContentProviderOperation लागू नहीं किया है. इस समस्या को हल करने के लिए, ContentProviderOperation.Builder क्लास में withValueBackReference() तरीका मौजूद है.
इस तरीके से, किसी कॉलम को पिछली कार्रवाई के नतीजे के साथ डाला जा सकता है या उसमें बदलाव किया जा सकता है.
withValueBackReference()
तरीके में दो आर्ग्युमेंट होते हैं:
-
key - की-वैल्यू पेयर की कुंजी. इस आर्ग्युमेंट की वैल्यू, उस टेबल के कॉलम का नाम होनी चाहिए जिसमें बदलाव किया जा रहा है.
-
previousResult -
applyBatch()सेContentProviderResultऑब्जेक्ट के कलेक्शन में, वैल्यू का 0-आधारित इंडेक्स. बैच ऑपरेशन लागू होने पर, हर ऑपरेशन का नतीजा, नतीजों के इंटरमीडिएट कलेक्शन में सेव हो जाता है.previousResultवैल्यू, इनमें से किसी एक नतीजे का इंडेक्स होती है. इसेkeyवैल्यू के साथ वापस लाया जाता है और सेव किया जाता है. इससे आपको एक नया रॉ कॉन्टैक्ट रिकॉर्ड डालने और उसकी_IDवैल्यू वापस पाने की सुविधा मिलती है. इसके बाद,ContactsContract.Dataलाइन जोड़ते समय वैल्यू का "बैक रेफ़रंस" बनाएं.जब आप पहली बार
applyBatch()को कॉल करते हैं, तब पूरा नतीजा ऐरे बनता है. इसका साइज़, आपके दिए गएContentProviderOperationऑब्जेक्ट केArrayListके साइज़ के बराबर होता है. हालांकि, नतीजे के कलेक्शन में मौजूद सभी एलिमेंट कोnullपर सेट किया जाता है. साथ ही, अगर किसी ऐसे ऑपरेशन के नतीजे का बैक रेफ़रंस देने की कोशिश की जाती है जो अब तक लागू नहीं हुआ है, तोwithValueBackReference(),Exceptionदिखाता है.
यहां दिए गए स्निपेट में, बैच में नया रॉ कॉन्टैक्ट और डेटा डालने का तरीका बताया गया है. इनमें ऐसा कोड शामिल होता है जो यील्ड पॉइंट सेट करता है और बैक रेफ़रंस का इस्तेमाल करता है.
पहला स्निपेट, यूज़र इंटरफ़ेस (यूआई) से संपर्क डेटा को वापस लाता है. इस समय, उपयोगकर्ता ने पहले ही वह खाता चुन लिया है जिसके लिए नया रॉ कॉन्टैक्ट जोड़ा जाना चाहिए.
Kotlin
// Creates a contact entry from the current UI values, using the currently-selected account. private fun createContactEntry() { /* * Gets values from the UI */ val name = contactNameEditText.text.toString() val phone = contactPhoneEditText.text.toString() val email = contactEmailEditText.text.toString() val phoneType: String = contactPhoneTypes[mContactPhoneTypeSpinner.selectedItemPosition] val emailType: String = contactEmailTypes[mContactEmailTypeSpinner.selectedItemPosition]
Java
// Creates a contact entry from the current UI values, using the currently-selected account. protected void createContactEntry() { /* * Gets values from the UI */ String name = contactNameEditText.getText().toString(); String phone = contactPhoneEditText.getText().toString(); String email = contactEmailEditText.getText().toString(); int phoneType = contactPhoneTypes.get( contactPhoneTypeSpinner.getSelectedItemPosition()); int emailType = contactEmailTypes.get( contactEmailTypeSpinner.getSelectedItemPosition());
अगला स्निपेट, ContactsContract.RawContacts टेबल में रॉ कॉन्टैक्ट की पंक्ति को शामिल करने के लिए एक कार्रवाई बनाता है:
Kotlin
/* * Prepares the batch operation for inserting a new raw contact and its data. Even if * the Contacts Provider does not have any data for this person, you can't add a Contact, * only a raw contact. The Contacts Provider will then add a Contact automatically. */ // Creates a new array of ContentProviderOperation objects. val ops = arrayListOf<ContentProviderOperation>() /* * Creates a new raw contact with its account type (server type) and account name * (user's account). Remember that the display name is not stored in this row, but in a * StructuredName data row. No other data is required. */ var op: ContentProviderOperation.Builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.name) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.type) // Builds the operation and adds it to the array of operations ops.add(op.build())
Java
/* * Prepares the batch operation for inserting a new raw contact and its data. Even if * the Contacts Provider does not have any data for this person, you can't add a Contact, * only a raw contact. The Contacts Provider will then add a Contact automatically. */ // Creates a new array of ContentProviderOperation objects. ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); /* * Creates a new raw contact with its account type (server type) and account name * (user's account). Remember that the display name is not stored in this row, but in a * StructuredName data row. No other data is required. */ ContentProviderOperation.Builder op = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.getType()) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.getName()); // Builds the operation and adds it to the array of operations ops.add(op.build());
इसके बाद, कोड डिसप्ले नेम, फ़ोन, और ईमेल की पंक्तियों के लिए डेटा पंक्तियां बनाता है.
हर ऑपरेशन बिल्डर ऑब्जेक्ट,
RAW_CONTACT_ID
पाने के लिए
withValueBackReference()
का इस्तेमाल करता है. रेफ़रंस, पहले ऑपरेशन के ContentProviderResult ऑब्जेक्ट पर वापस ले जाता है. यह ऑब्जेक्ट, रॉ कॉन्टैक्ट की लाइन जोड़ता है और उसकी नई _ID वैल्यू दिखाता है. इस वजह से, डेटा की हर लाइन अपने-आप RAW_CONTACT_ID से लिंक हो जाती है. यह लिंक, ContactsContract.RawContacts की उस नई लाइन से होता है जिससे वह जुड़ी होती है.
ईमेल की लाइन जोड़ने वाले ContentProviderOperation.Builder ऑब्जेक्ट को withYieldAllowed() के साथ फ़्लैग किया गया है. इससे एक यील्ड पॉइंट सेट होता है:
Kotlin
// Creates the display name for the new raw contact, as a StructuredName data row. op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * withValueBackReference sets the value of the first argument to the value of * the ContentProviderResult indexed by the second argument. In this particular * call, the raw contact ID column of the StructuredName data row is set to the * value of the result returned by the first operation, which is the one that * actually adds the raw contact row. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to StructuredName .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) // Sets the data row's display name to the name in the UI. .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name) // Builds the operation and adds it to the array of operations ops.add(op.build()) // Inserts the specified phone number and type as a Phone data row op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * Sets the value of the raw contact id column to the new raw contact ID returned * by the first operation in the batch. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to Phone .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) // Sets the phone number and type .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType) // Builds the operation and adds it to the array of operations ops.add(op.build()) // Inserts the specified email and type as a Phone data row op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * Sets the value of the raw contact id column to the new raw contact ID returned * by the first operation in the batch. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to Email .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) // Sets the email address and type .withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email) .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType) /* * Demonstrates a yield point. At the end of this insert, the batch operation's thread * will yield priority to other threads. Use after every set of operations that affect a * single contact, to avoid degrading performance. */ op.withYieldAllowed(true) // Builds the operation and adds it to the array of operations ops.add(op.build())
Java
// Creates the display name for the new raw contact, as a StructuredName data row. op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * withValueBackReference sets the value of the first argument to the value of * the ContentProviderResult indexed by the second argument. In this particular * call, the raw contact ID column of the StructuredName data row is set to the * value of the result returned by the first operation, which is the one that * actually adds the raw contact row. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to StructuredName .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) // Sets the data row's display name to the name in the UI. .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name); // Builds the operation and adds it to the array of operations ops.add(op.build()); // Inserts the specified phone number and type as a Phone data row op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * Sets the value of the raw contact id column to the new raw contact ID returned * by the first operation in the batch. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to Phone .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) // Sets the phone number and type .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType); // Builds the operation and adds it to the array of operations ops.add(op.build()); // Inserts the specified email and type as a Phone data row op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * Sets the value of the raw contact id column to the new raw contact ID returned * by the first operation in the batch. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to Email .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) // Sets the email address and type .withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email) .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType); /* * Demonstrates a yield point. At the end of this insert, the batch operation's thread * will yield priority to other threads. Use after every set of operations that affect a * single contact, to avoid degrading performance. */ op.withYieldAllowed(true); // Builds the operation and adds it to the array of operations ops.add(op.build());
आखिरी स्निपेट में, applyBatch() को किया गया कॉल दिखाया गया है. यह कॉल, नए रॉ कॉन्टैक्ट और डेटा की पंक्तियां शामिल करता है.
Kotlin
// Ask the Contacts Provider to create a new contact Log.d(TAG, "Selected account: ${mSelectedAccount.name} (${mSelectedAccount.type})") Log.d(TAG, "Creating contact: $name") /* * Applies the array of ContentProviderOperation objects in batch. The results are * discarded. */ try { contentResolver.applyBatch(ContactsContract.AUTHORITY, ops) } catch (e: Exception) { // Display a warning val txt: String = getString(R.string.contactCreationFailure) Toast.makeText(applicationContext, txt, Toast.LENGTH_SHORT).show() // Log exception Log.e(TAG, "Exception encountered while inserting contact: $e") } }
Java
// Ask the Contacts Provider to create a new contact Log.d(TAG,"Selected account: " + selectedAccount.getName() + " (" + selectedAccount.getType() + ")"); Log.d(TAG,"Creating contact: " + name); /* * Applies the array of ContentProviderOperation objects in batch. The results are * discarded. */ try { getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { // Display a warning Context ctx = getApplicationContext(); CharSequence txt = getString(R.string.contactCreationFailure); int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(ctx, txt, duration); toast.show(); // Log exception Log.e(TAG, "Exception encountered while inserting contact: " + e); } }
बैच ऑपरेशन की मदद से, ऑप्टिमिस्टिक कॉनकरेंसी कंट्रोल को भी लागू किया जा सकता है. यह बदलाव करने वाले लेन-देन को लागू करने का एक तरीका है. इसके लिए, डेटा स्टोर करने की जगह को लॉक करने की ज़रूरत नहीं होती. इस तरीके का इस्तेमाल करने के लिए, लेन-देन को लागू करें. इसके बाद, उन अन्य बदलावों की जांच करें जो उसी समय किए गए हों. अगर आपको लगता है कि कोई बदलाव गलत तरीके से हुआ है, तो लेन-देन को पहले जैसा करें और फिर से कोशिश करें.
ऑप्टिमिस्टिक कॉनकरंसी कंट्रोल, मोबाइल डिवाइस के लिए मददगार होता है. इसमें एक समय पर सिर्फ़ एक उपयोगकर्ता होता है. साथ ही, डेटा रिपॉज़िटरी को एक साथ ऐक्सेस करने के मामले बहुत कम होते हैं. लॉक करने की सुविधा का इस्तेमाल नहीं किया जाता है. इसलिए, लॉक सेट करने या अन्य लेन-देन के लॉक रिलीज़ होने का इंतज़ार करने में समय बर्बाद नहीं होता है.
ContactsContract.RawContacts की किसी एक लाइन को अपडेट करते समय, ऑप्टिमिस्टिक कॉनकरंसी कंट्रोल का इस्तेमाल करने के लिए, यह तरीका अपनाएं:
-
रॉ कॉन्टैक्ट के
VERSIONकॉलम को वापस लाएं. साथ ही, अन्य डेटा को भी वापस लाएं. -
newAssertQuery(Uri)तरीके का इस्तेमाल करके, पाबंदी लागू करने के लिए सहीContentProviderOperation.Builderऑब्जेक्ट बनाएं. कॉन्टेंट यूआरआई के लिए,RawContacts.CONTENT_URIका इस्तेमाल करें. साथ ही, इसमें रॉ कॉन्टैक्ट का_IDजोड़ें. -
ContentProviderOperation.Builderऑब्जेक्ट के लिए,withValue()को कॉल करें, ताकिVERSIONकॉलम की तुलना, अभी-अभी मिले वर्शन नंबर से की जा सके. -
उसी
ContentProviderOperation.Builderके लिए,withExpectedCount()को कॉल करें, ताकि यह पक्का किया जा सके कि इस दावे से सिर्फ़ एक लाइन की जांच की गई है. -
ContentProviderOperationऑब्जेक्ट बनाने के लिए,build()को कॉल करें. इसके बाद, इस ऑब्जेक्ट कोArrayListमें पहले ऑब्जेक्ट के तौर पर जोड़ें. इसेapplyBatch()को पास करें. - बैच लेन-देन लागू करें.
अगर रॉ कॉन्टैक्ट की लाइन को पढ़ने और उसमें बदलाव करने के बीच, किसी अन्य कार्रवाई से उसे अपडेट किया जाता है, तो "assert" ContentProviderOperation
काम नहीं करेगा. साथ ही, कार्रवाइयों के पूरे बैच को वापस ले लिया जाएगा. इसके बाद, आपके पास बैच को फिर से प्रोसेस करने या कोई अन्य कार्रवाई करने का विकल्प होता है.
यहां दिए गए स्निपेट में, CursorLoader का इस्तेमाल करके किसी एक रॉ कॉन्टैक्ट के लिए क्वेरी करने के बाद, "assert" ContentProviderOperation बनाने का तरीका बताया गया है:
Kotlin
/* * The application uses CursorLoader to query the raw contacts table. The system calls this method * when the load is finished. */ override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor) { // Gets the raw contact's _ID and VERSION values rawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID)) mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION)) } ... // Sets up a Uri for the assert operation val rawContactUri: Uri = ContentUris.withAppendedId( ContactsContract.RawContacts.CONTENT_URI, rawContactID ) // Creates a builder for the assert operation val assertOp: ContentProviderOperation.Builder = ContentProviderOperation.newAssertQuery(rawContactUri).apply { // Adds the assertions to the assert operation: checks the version withValue(SyncColumns.VERSION, mVersion) // and count of rows tested withExpectedCount(1) } // Creates an ArrayList to hold the ContentProviderOperation objects val ops = arrayListOf<ContentProviderOperation>() ops.add(assertOp.build()) // You would add the rest of your batch operations to "ops" here ... // Applies the batch. If the assert fails, an Exception is thrown try { val results: Array<ContentProviderResult> = contentResolver.applyBatch(AUTHORITY, ops) } catch (e: OperationApplicationException) { // Actions you want to take if the assert operation fails go here }
Java
/* * The application uses CursorLoader to query the raw contacts table. The system calls this method * when the load is finished. */ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { // Gets the raw contact's _ID and VERSION values rawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID)); mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION)); } ... // Sets up a Uri for the assert operation Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactID); // Creates a builder for the assert operation ContentProviderOperation.Builder assertOp = ContentProviderOperation.newAssertQuery(rawContactUri); // Adds the assertions to the assert operation: checks the version and count of rows tested assertOp.withValue(SyncColumns.VERSION, mVersion); assertOp.withExpectedCount(1); // Creates an ArrayList to hold the ContentProviderOperation objects ArrayList ops = new ArrayList<ContentProviderOperation>; ops.add(assertOp.build()); // You would add the rest of your batch operations to "ops" here ... // Applies the batch. If the assert fails, an Exception is thrown try { ContentProviderResult[] results = getContentResolver().applyBatch(AUTHORITY, ops); } catch (OperationApplicationException e) { // Actions you want to take if the assert operation fails go here }
इंटेंट की मदद से जानकारी पाना और उसमें बदलाव करना
डिवाइस के संपर्क ऐप्लिकेशन पर इंटेंट भेजने से, आपको संपर्क सूची को अप्रत्यक्ष रूप से ऐक्सेस करने की सुविधा मिलती है. इंटेंट, डिवाइस के संपर्क ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) शुरू करता है. इसमें उपयोगकर्ता, संपर्कों से जुड़ा काम कर सकते हैं. इस तरह के ऐक्सेस वाले उपयोगकर्ता ये काम कर सकते हैं:
- सूची से कोई संपर्क चुनें और उसे अपने ऐप्लिकेशन में वापस लाएं, ताकि आगे का काम किया जा सके.
- किसी मौजूदा संपर्क के डेटा में बदलाव करना.
- किसी भी खाते के लिए, नया रॉ कॉन्टैक्ट जोड़ना.
- किसी संपर्क या संपर्कों का डेटा मिटाना.
अगर उपयोगकर्ता डेटा डाल रहा है या अपडेट कर रहा है, तो पहले डेटा इकट्ठा किया जा सकता है. इसके बाद, उसे इंटेंट के हिस्से के तौर पर भेजा जा सकता है.
डिवाइस के संपर्क ऐप्लिकेशन के ज़रिए संपर्क सूची को ऐक्सेस करने के लिए इंटेंट का इस्तेमाल करने पर, आपको संपर्क सूची को ऐक्सेस करने के लिए अपना यूज़र इंटरफ़ेस (यूआई) या कोड लिखने की ज़रूरत नहीं पड़ती. आपको सेवा देने वाली कंपनी से, डेटा को पढ़ने या उसमें बदलाव करने की अनुमति का अनुरोध करने की भी ज़रूरत नहीं है. डिवाइस का संपर्क ऐप्लिकेशन, आपको किसी संपर्क को पढ़ने की अनुमति दे सकता है. साथ ही, सेवा देने वाली कंपनी में किसी दूसरे ऐप्लिकेशन के ज़रिए बदलाव किए जा रहे हैं, इसलिए आपको फ़ाइल या एंट्री में बदलाव करने की अनुमति की ज़रूरत नहीं है.
किसी प्रोवाइडर को ऐक्सेस करने के लिए इंटेंट भेजने की सामान्य प्रोसेस के बारे में,
कॉन्टेंट देने वाले के बारे में बुनियादी जानकारी गाइड के "इंटेंट के ज़रिए डेटा ऐक्सेस करना" सेक्शन में बताया गया है. उपलब्ध टास्क के लिए इस्तेमाल की जाने वाली कार्रवाई, एमआईएमई टाइप, और डेटा वैल्यू की खास जानकारी टेबल 4 में दी गई है. वहीं, putExtra() के साथ इस्तेमाल की जा सकने वाली अतिरिक्त वैल्यू, ContactsContract.Intents.Insert के रेफ़रंस दस्तावेज़ में दी गई हैं:
टेबल 4. संपर्क सूची के इंटेंट.
| टास्क | कार्रवाई | डेटा | MIME टाइप | नोट |
|---|---|---|---|---|
| सूची से कोई संपर्क चुनना | ACTION_PICK |
इनमें से एक:
|
उपयोग नहीं किया गया |
यह रॉ कॉन्टैक्ट की सूची या रॉ कॉन्टैक्ट से मिले डेटा की सूची दिखाता है. यह आपके दिए गए कॉन्टेंट यूआरआई के टाइप पर निर्भर करता है.
|
| नया रॉ कॉन्टैक्ट जोड़ना | Insert.ACTION |
लागू नहीं |
RawContacts.CONTENT_TYPE, रॉ कॉन्टैक्ट के सेट के लिए एमआईएमई टाइप.
|
इससे डिवाइस के संपर्क ऐप्लिकेशन की संपर्क जोड़ें स्क्रीन दिखती है. इंटेंट में जोड़ी गई अतिरिक्त वैल्यू दिखती हैं. अगर
startActivityForResult() के साथ भेजा जाता है,
तो नए जोड़े गए रॉ कॉन्टैक्ट का कॉन्टेंट यूआरआई, आपकी गतिविधि के
onActivityResult()
कॉलबैक के तरीके में Intent आर्ग्युमेंट में,
"डेटा" फ़ील्ड में वापस भेज दिया जाता है. वैल्यू पाने के लिए, getData() को कॉल करें.
|
| किसी संपर्क की जानकारी में बदलाव करना | ACTION_EDIT |
CONTENT_LOOKUP_URI को
संपर्क के तौर पर सेट किया गया है. एडिटर ऐक्टिविटी की मदद से, उपयोगकर्ता इस संपर्क से जुड़े किसी भी डेटा में बदलाव कर पाएगा.
|
Contacts.CONTENT_ITEM_TYPE, एक संपर्क. |
संपर्क ऐप्लिकेशन में, 'संपर्क में बदलाव करें' स्क्रीन दिखाता है. इंटेंट में जोड़ी गई अतिरिक्त वैल्यू दिखाई जाती हैं. जब उपयोगकर्ता बदलावों को सेव करने के लिए हो गया पर क्लिक करता है, तो आपकी गतिविधि फ़ोरग्राउंड में वापस आ जाती है. |
| ऐसा पिकर दिखाएं जो डेटा भी जोड़ सके. | ACTION_INSERT_OR_EDIT |
लागू नहीं |
CONTENT_ITEM_TYPE
|
यह इंटेंट, संपर्क ऐप्लिकेशन की पिकर स्क्रीन को हमेशा दिखाता है. उपयोगकर्ता, किसी संपर्क में बदलाव करने के लिए उसे चुन सकता है या नया संपर्क जोड़ सकता है. उपयोगकर्ता की पसंद के आधार पर, बदलाव करने या जोड़ने वाली स्क्रीन दिखती है. साथ ही, इंटेंट में पास किया गया अतिरिक्त डेटा दिखता है. अगर आपका ऐप्लिकेशन, ईमेल या फ़ोन नंबर जैसा संपर्क डेटा दिखाता है, तो इस इंटेंट का इस्तेमाल करें. इससे उपयोगकर्ता, किसी मौजूदा संपर्क में डेटा जोड़ पाएगा.
संपर्क,
ध्यान दें: इस इंटेंट के अतिरिक्त फ़ील्ड में नाम की वैल्यू भेजने की ज़रूरत नहीं है, क्योंकि उपयोगकर्ता हमेशा कोई मौजूदा नाम चुनता है या नया नाम जोड़ता है. इसके अलावा, अगर आपने कोई नाम भेजा है और उपयोगकर्ता उसमें बदलाव करता है, तो संपर्क ऐप्लिकेशन में आपके भेजे गए नाम को दिखाया जाएगा. इससे, पिछली वैल्यू को ओवरराइट कर दिया जाएगा. अगर उपयोगकर्ता इस पर ध्यान नहीं देता है और बदलाव को सेव कर लेता है, तो पुरानी वैल्यू मिट जाती है. |
डिवाइस का संपर्क ऐप्लिकेशन, आपको किसी रॉ कॉन्टैक्ट या उसके किसी डेटा को इंटेंट की मदद से मिटाने की अनुमति नहीं देता. इसके बजाय, किसी रॉ कॉन्टैक्ट को मिटाने के लिए, ContentResolver.delete()
या ContentProviderOperation.newDelete() का इस्तेमाल करें.
यहां दिए गए स्निपेट में, नया रॉ कॉन्टैक्ट और डेटा डालने वाला इंटेंट बनाने और भेजने का तरीका बताया गया है:
Kotlin
// Gets values from the UI val name = contactNameEditText.text.toString() val phone = contactPhoneEditText.text.toString() val email = contactEmailEditText.text.toString() val company = companyName.text.toString() val jobtitle = jobTitle.text.toString() /* * Demonstrates adding data rows as an array list associated with the DATA key */ // Defines an array list to contain the ContentValues objects for each row val contactData = arrayListOf<ContentValues>() /* * Defines the raw contact row */ // Sets up the row as a ContentValues object val rawContactRow = ContentValues().apply { // Adds the account type and name to the row put(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.type) put(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.name) } // Adds the row to the array contactData.add(rawContactRow) /* * Sets up the phone number data row */ // Sets up the row as a ContentValues object val phoneRow = ContentValues().apply { // Specifies the MIME type for this data row (all data rows must be marked by their type) put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) // Adds the phone number and its type to the row put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) } // Adds the row to the array contactData.add(phoneRow) /* * Sets up the email data row */ // Sets up the row as a ContentValues object val emailRow = ContentValues().apply { // Specifies the MIME type for this data row (all data rows must be marked by their type) put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) // Adds the email address and its type to the row put(ContactsContract.CommonDataKinds.Email.ADDRESS, email) } // Adds the row to the array contactData.add(emailRow) // Creates a new intent for sending to the device's contacts application val insertIntent = Intent(ContactsContract.Intents.Insert.ACTION).apply { // Sets the MIME type to the one expected by the insertion activity type = ContactsContract.RawContacts.CONTENT_TYPE // Sets the new contact name putExtra(ContactsContract.Intents.Insert.NAME, name) // Sets the new company and job title putExtra(ContactsContract.Intents.Insert.COMPANY, company) putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle) /* * Adds the array to the intent's extras. It must be a parcelable object in order to * travel between processes. The device's contacts app expects its key to be * Intents.Insert.DATA */ putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData) } // Send out the intent to start the device's contacts app in its add contact activity. startActivity(insertIntent)
Java
// Gets values from the UI String name = contactNameEditText.getText().toString(); String phone = contactPhoneEditText.getText().toString(); String email = contactEmailEditText.getText().toString(); String company = companyName.getText().toString(); String jobtitle = jobTitle.getText().toString(); // Creates a new intent for sending to the device's contacts application Intent insertIntent = new Intent(ContactsContract.Intents.Insert.ACTION); // Sets the MIME type to the one expected by the insertion activity insertIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE); // Sets the new contact name insertIntent.putExtra(ContactsContract.Intents.Insert.NAME, name); // Sets the new company and job title insertIntent.putExtra(ContactsContract.Intents.Insert.COMPANY, company); insertIntent.putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle); /* * Demonstrates adding data rows as an array list associated with the DATA key */ // Defines an array list to contain the ContentValues objects for each row ArrayList<ContentValues> contactData = new ArrayList<ContentValues>(); /* * Defines the raw contact row */ // Sets up the row as a ContentValues object ContentValues rawContactRow = new ContentValues(); // Adds the account type and name to the row rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.getType()); rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.getName()); // Adds the row to the array contactData.add(rawContactRow); /* * Sets up the phone number data row */ // Sets up the row as a ContentValues object ContentValues phoneRow = new ContentValues(); // Specifies the MIME type for this data row (all data rows must be marked by their type) phoneRow.put( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE ); // Adds the phone number and its type to the row phoneRow.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone); // Adds the row to the array contactData.add(phoneRow); /* * Sets up the email data row */ // Sets up the row as a ContentValues object ContentValues emailRow = new ContentValues(); // Specifies the MIME type for this data row (all data rows must be marked by their type) emailRow.put( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE ); // Adds the email address and its type to the row emailRow.put(ContactsContract.CommonDataKinds.Email.ADDRESS, email); // Adds the row to the array contactData.add(emailRow); /* * Adds the array to the intent's extras. It must be a parcelable object in order to * travel between processes. The device's contacts app expects its key to be * Intents.Insert.DATA */ insertIntent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData); // Send out the intent to start the device's contacts app in its add contact activity. startActivity(insertIntent);
डेटा का रखरखाव
संपर्क सूची में अहम और संवेदनशील डेटा होता है. उपयोगकर्ताओं को उम्मीद होती है कि यह डेटा सही और अप-टू-डेट हो. इसलिए, संपर्क सूची में डेटा के रखरखाव के लिए साफ़ तौर पर नियम तय किए गए हैं. संपर्कों के डेटा में बदलाव करते समय, इन नियमों का पालन करना आपकी ज़िम्मेदारी है. ज़रूरी नियम यहां दिए गए हैं:
-
जोड़ी गई हर
ContactsContract.RawContactsलाइन के लिए, हमेशा एकContactsContract.CommonDataKinds.StructuredNameलाइन जोड़ें. -
ContactsContract.Dataटेबल में,ContactsContract.CommonDataKinds.StructuredNameलाइन के बिनाContactsContract.RawContactsलाइन होने पर, एग्रीगेशन के दौरान समस्याएं आ सकती हैं. -
ContactsContract.Dataकी नई पंक्तियों को हमेशा उनकी पैरंटContactsContract.RawContactsपंक्ति से लिंक करें. -
ContactsContract.Dataकी ऐसी लाइन जोContactsContract.RawContactsसे लिंक नहीं है, वह डिवाइस के संपर्क ऐप्लिकेशन में नहीं दिखेगी. साथ ही, इससे सिंक अडैप्टर में समस्याएं आ सकती हैं. - सिर्फ़ उन रॉ कॉन्टैक्ट का डेटा बदलें जिनका मालिकाना हक आपके पास है.
- याद रखें कि संपर्क सूची, आम तौर पर कई अलग-अलग तरह के खातों/ऑनलाइन सेवाओं के डेटा को मैनेज करती है. आपको यह पक्का करना होगा कि आपका ऐप्लिकेशन सिर्फ़ उन पंक्तियों के डेटा में बदलाव करे या उन्हें मिटाए जो आपसे जुड़ी हैं. साथ ही, यह भी पक्का करना होगा कि वह सिर्फ़ उस खाता टाइप और नाम के साथ डेटा डाले जिसे आप कंट्रोल करते हैं.
-
अथॉरिटी, कॉन्टेंट यूआरआई, यूआरआई पाथ, कॉलम के नाम, एमआईएमई टाइप, और
TYPEवैल्यू के लिए, हमेशाContactsContractऔर इसकी सबक्लास में तय किए गए कॉन्स्टेंट का इस्तेमाल करें. - इन कॉन्स्टेंट का इस्तेमाल करने से, गड़बड़ियों से बचा जा सकता है. अगर कोई कॉन्सटैंट अब काम नहीं करता है, तो आपको कंपाइलर से जुड़ी चेतावनियों के साथ सूचना दी जाएगी.
कस्टम डेटा की लाइनें
अपने कस्टम एमआईएमई टाइप बनाकर और उनका इस्तेमाल करके, ContactsContract.Data टेबल में अपने डेटा की लाइनें डाली जा सकती हैं, उनमें बदलाव किया जा सकता है, उन्हें मिटाया जा सकता है, और वापस लाया जा सकता है. आपकी पंक्तियां, ContactsContract.DataColumns में तय किए गए कॉलम का इस्तेमाल करने तक सीमित हैं. हालांकि, आपके पास अपने टाइप के हिसाब से कॉलम के नामों को डिफ़ॉल्ट कॉलम के नामों से मैप करने का विकल्प होता है. डिवाइस के संपर्क ऐप्लिकेशन में,
आपकी पंक्तियों का डेटा दिखता है. हालांकि, उसमें बदलाव नहीं किया जा सकता या उसे मिटाया नहीं जा सकता. साथ ही, उपयोगकर्ता
ज़्यादा डेटा नहीं जोड़ सकते. उपयोगकर्ताओं को कस्टम डेटा की पंक्तियों में बदलाव करने की अनुमति देने के लिए, आपको अपने ऐप्लिकेशन में एडिटर ऐक्टिविटी उपलब्ध करानी होगी.
अपना ग्राहक से जुड़ा डेटा दिखाने के लिए, contacts.xml फ़ाइल सबमिट करें. इसमें <ContactsAccountType> एलिमेंट और इसके एक या उससे ज़्यादा <ContactsDataKind> चाइल्ड एलिमेंट होने चाहिए. इस बारे में ज़्यादा जानकारी, <ContactsDataKind> element सेक्शन में दी गई है.
कस्टम एमआईएमई टाइप के बारे में ज़्यादा जानने के लिए, कॉन्टेंट प्रोवाइडर बनाएं गाइड पढ़ें.
संपर्क सूची के सिंक अडैप्टर
संपर्क सूची को खास तौर पर, किसी डिवाइस और ऑनलाइन सेवा के बीच संपर्क डेटा के सिंक्रनाइज़ेशन को मैनेज करने के लिए डिज़ाइन किया गया है. इससे उपयोगकर्ता, मौजूदा डेटा को नए डिवाइस पर डाउनलोड कर सकते हैं और मौजूदा डेटा को नए खाते में अपलोड कर सकते हैं. सिंक करने से यह भी पक्का होता है कि उपयोगकर्ताओं के पास हमेशा अप-टू-डेट डेटा हो. भले ही, डेटा में बदलाव या उसे जोड़ने का सोर्स कुछ भी हो. सिंक करने का एक और फ़ायदा यह है कि डिवाइस के नेटवर्क से कनेक्ट न होने पर भी, संपर्कों का डेटा उपलब्ध रहता है.
सिंक करने की सुविधा को कई तरीकों से लागू किया जा सकता है. हालांकि, Android सिस्टम, प्लग-इन सिंक करने वाला फ़्रेमवर्क उपलब्ध कराता है. यह फ़्रेमवर्क, इन टास्क को अपने-आप पूरा करता है:
- नेटवर्क की उपलब्धता की जांच की जा रही है.
- उपयोगकर्ता की प्राथमिकताओं के आधार पर, सिंक करने की प्रोसेस को शेड्यूल करना और उसे लागू करना.
- रुके हुए सिंक को फिर से शुरू करना.
इस फ़्रेमवर्क का इस्तेमाल करने के लिए, आपको सिंक अडैप्टर प्लग-इन देना होगा. हर सिंक अडैप्टर, किसी सेवा और कॉन्टेंट देने वाले के लिए यूनीक होता है. हालांकि, यह एक ही सेवा के लिए कई खातों के नाम मैनेज कर सकता है. यह फ़्रेमवर्क, एक ही सेवा और सेवा देने वाली कंपनी के लिए कई सिंक अडैप्टर इस्तेमाल करने की अनुमति भी देता है.
सिंक अडैप्टर क्लास और फ़ाइलें
सिंक अडैप्टर को AbstractThreadedSyncAdapter की सबक्लास के तौर पर लागू किया जाता है और इसे Android ऐप्लिकेशन के हिस्से के तौर पर इंस्टॉल किया जाता है. सिस्टम, आपके ऐप्लिकेशन मेनिफ़ेस्ट में मौजूद एलिमेंट और मेनिफ़ेस्ट में बताई गई खास एक्सएमएल फ़ाइल से, सिंक अडैप्टर के बारे में जानकारी हासिल करता है. एक्सएमएल फ़ाइल, ऑनलाइन सेवा के लिए खाता टाइप और कॉन्टेंट देने वाले के लिए अथॉरिटी तय करती है. ये दोनों मिलकर, अडैप्टर की खास तौर पर पहचान करते हैं. सिंक अडैप्टर तब तक चालू नहीं होता, जब तक उपयोगकर्ता सिंक अडैप्टर के खाता टाइप के लिए कोई खाता नहीं जोड़ता. साथ ही, कॉन्टेंट देने वाले उस व्यक्ति या कंपनी के लिए सिंक करने की सुविधा चालू नहीं करता जिसके साथ सिंक अडैप्टर सिंक करता है. इसके बाद, सिस्टम अडैप्टर को मैनेज करना शुरू कर देता है. साथ ही, कॉन्टेंट देने वाले और सर्वर के बीच सिंक करने के लिए, ज़रूरत के हिसाब से उसे कॉल करता है.
ध्यान दें: सिंक अडैप्टर की पहचान के हिस्से के तौर पर खाता टाइप का इस्तेमाल करने से, सिस्टम को उन सिंक अडैप्टर का पता लगाने और उन्हें एक साथ ग्रुप करने में मदद मिलती है जो एक ही संगठन की अलग-अलग सेवाओं को ऐक्सेस करते हैं. उदाहरण के लिए, Google की ऑनलाइन सेवाओं के लिए सभी सिंक अडैप्टर का खाता टाइप com.google एक जैसा होता है. जब उपयोगकर्ता अपने डिवाइसों में कोई Google खाता जोड़ते हैं, तो Google की सेवाओं के लिए इंस्टॉल किए गए सभी सिंक अडैप्टर एक साथ दिखते हैं. सूची में मौजूद हर सिंक अडैप्टर, डिवाइस पर कॉन्टेंट देने वाले अलग-अलग ऐप्लिकेशन के साथ सिंक होता है.
ज़्यादातर सेवाओं में, डेटा ऐक्सेस करने से पहले उपयोगकर्ताओं को अपनी पहचान की पुष्टि करनी होती है. इसलिए, Android सिस्टम, पुष्टि करने वाला एक फ़्रेमवर्क उपलब्ध कराता है. यह फ़्रेमवर्क, सिंक अडैप्टर फ़्रेमवर्क जैसा ही होता है और अक्सर इसके साथ इस्तेमाल किया जाता है. पुष्टि करने वाला फ़्रेमवर्क, प्लग-इन ऑथेंटिकेटर का इस्तेमाल करता है. ये AbstractAccountAuthenticator की सबक्लास होती हैं. पुष्टि करने वाला ऐप्लिकेशन, उपयोगकर्ता की पहचान की पुष्टि इन चरणों में करता है:
- उपयोगकर्ता का नाम, पासवर्ड या मिलती-जुलती जानकारी (उपयोगकर्ता के क्रेडेंशियल) इकट्ठा करता है.
- सेवा को क्रेडेंशियल भेजता है
- सेवा से मिले जवाब की जांच करता है.
अगर सेवा क्रेडेंशियल स्वीकार करती है, तो पुष्टि करने वाला ऐप्लिकेशन, क्रेडेंशियल को बाद में इस्तेमाल करने के लिए सेव कर सकता है. प्लग-इन ऑथेंटिकेटर फ़्रेमवर्क की वजह से, AccountManager किसी भी ऑथेंटिकेशन टोकन का ऐक्सेस दे सकता है. हालांकि, इसके लिए ज़रूरी है कि ऑथेंटिकेटर उस टोकन को सपोर्ट करता हो और उसे एक्सपोज़ करने का विकल्प चुना गया हो. जैसे, OAuth2 ऑथेंटिकेशन टोकन.
हालांकि, पुष्टि करना ज़रूरी नहीं है, लेकिन संपर्क की ज़्यादातर सेवाएं इसका इस्तेमाल करती हैं. हालांकि, पुष्टि करने के लिए Android के ऑथेंटिकेशन फ़्रेमवर्क का इस्तेमाल करना ज़रूरी नहीं है.
सिंक अडैप्टर को लागू करना
संपर्क सूची के लिए सिंक अडैप्टर लागू करने के लिए, आपको एक Android ऐप्लिकेशन बनाना होगा. इसमें ये चीज़ें शामिल होनी चाहिए:
-
Serviceका एक कॉम्पोनेंट, जो सिंक अडैप्टर से बाइंड करने के लिए सिस्टम से मिले अनुरोधों का जवाब देता है. -
जब सिस्टम को सिंक करना होता है, तो वह सेवा के
onBind()तरीके को कॉल करता है, ताकि सिंक अडैप्टर के लिएIBinderमिल सके. इससे सिस्टम, अडैप्टर के तरीकों को क्रॉस-प्रोसेस कॉल कर सकता है. -
असल सिंक अडैप्टर, जिसे
AbstractThreadedSyncAdapterके कॉन्क्रीट सबक्लास के तौर पर लागू किया गया है. -
यह क्लास, सर्वर से डेटा डाउनलोड करने, डिवाइस से डेटा अपलोड करने, और समस्याओं को हल करने का काम करती है. अडैप्टर का मुख्य काम,
onPerformSync()तरीके से किया जाता है. इस क्लास को सिंगलटन के तौर पर इंस्टैंशिएट किया जाना चाहिए. -
Applicationकी सबक्लास. -
यह क्लास, सिंक अडैप्टर सिंगलटन के लिए फ़ैक्ट्री के तौर पर काम करती है. सिंक अडैप्टर को इंस्टैंशिएट करने के लिए,
onCreate()तरीके का इस्तेमाल करें. साथ ही, सिंक अडैप्टर की सेवा केonBind()तरीके को सिंगलटन दिखाने के लिए, स्टैटिक "गेटर" तरीका उपलब्ध कराएं. -
ज़रूरी नहीं:
Serviceकॉम्पोनेंट, जो उपयोगकर्ता की पुष्टि करने के लिए सिस्टम से मिले अनुरोधों का जवाब देता है. -
AccountManager, पुष्टि की प्रक्रिया शुरू करने के लिए इस सेवा को चालू करता है. सेवा काonCreate()तरीका, एक ऑथेंटिकेटर ऑब्जेक्ट को इंस्टैंशिएट करता है. जब सिस्टम को ऐप्लिकेशन के सिंक अडैप्टर के लिए, किसी उपयोगकर्ता खाते की पुष्टि करनी होती है, तो वह सेवा केonBind()तरीके को कॉल करता है. इससे पुष्टि करने वाले के लिएIBinderमिलता है. इससे सिस्टम, पुष्टि करने वाले के तरीकों को क्रॉस-प्रोसेस कॉल कर सकता है.. -
ज़रूरी नहीं:
AbstractAccountAuthenticatorकी एक ठोस सबक्लास, जो पुष्टि करने के अनुरोधों को मैनेज करती है. -
यह क्लास ऐसे तरीके उपलब्ध कराती है जिन्हें
AccountManager, सर्वर पर उपयोगकर्ता के क्रेडेंशियल की पुष्टि करने के लिए इस्तेमाल करता है. पुष्टि करने की प्रक्रिया की जानकारी, इस्तेमाल की जा रही सर्वर टेक्नोलॉजी के हिसाब से अलग-अलग होती है. पुष्टि करने के बारे में ज़्यादा जानने के लिए, आपको अपने सर्वर सॉफ़्टवेयर के दस्तावेज़ देखने चाहिए. - एक्सएमएल फ़ाइलें, जो सिस्टम के लिए सिंक अडैप्टर और पुष्टि करने वाले टूल को तय करती हैं.
-
सिंक अडैप्टर और पुष्टि करने वाली सेवा के कॉम्पोनेंट के बारे में पहले बताया गया है.
इन्हें ऐप्लिकेशन मेनिफ़ेस्ट में
<service>एलिमेंट में तय किया गया है. इन एलिमेंट में<meta-data>चाइल्ड एलिमेंट होते हैं, जो सिस्टम को खास डेटा देते हैं:-
सिंक अडैप्टर सेवा के लिए,
<meta-data>एलिमेंट, एक्सएमएल फ़ाइलres/xml/syncadapter.xmlपर ले जाता है. इसके बाद, यह फ़ाइल उस वेब सेवा के लिए यूआरआई तय करती है जिसे संपर्क सूची के साथ सिंक किया जाएगा. साथ ही, यह वेब सेवा के लिए खाता टाइप तय करती है. -
ज़रूरी नहीं: ऑथेंटिकेटर के लिए
<meta-data>एलिमेंट, एक्सएमएल फ़ाइलres/xml/authenticator.xmlपर ले जाता है. इसके बाद, यह फ़ाइल उस खाते के टाइप के बारे में बताती है जो पुष्टि करने वाले इस ऐप्लिकेशन के साथ काम करता है. साथ ही, यह उन यूज़र इंटरफ़ेस (यूआई) संसाधनों के बारे में बताती है जो पुष्टि करने की प्रोसेस के दौरान दिखते हैं. इस एलिमेंट में बताया गया खाता टाइप, सिंक अडैप्टर के लिए बताए गए खाता टाइप से मेल खाना चाहिए.
-
सिंक अडैप्टर सेवा के लिए,
सोशल स्ट्रीम डेटा
android.provider.ContactsContract.StreamItems और android.provider.ContactsContract.StreamItemPhotos टेबल, सोशल नेटवर्क से आने वाले डेटा को मैनेज करती हैं. ऐसा सिंक अडैप्टर लिखा जा सकता है जो आपके नेटवर्क से इन टेबल में स्ट्रीम डेटा जोड़ता है. इसके अलावा, इन टेबल से स्ट्रीम डेटा को पढ़ा जा सकता है और उसे अपने ऐप्लिकेशन में दिखाया जा सकता है. इसके अलावा, दोनों काम किए जा सकते हैं. इन सुविधाओं की मदद से, आपकी सोशल नेटवर्किंग सेवाओं और ऐप्लिकेशन को Android के सोशल नेटवर्किंग अनुभव में इंटिग्रेट किया जा सकता है.
सोशल स्ट्रीम टेक्स्ट
स्ट्रीम आइटम हमेशा किसी रॉ कॉन्टैक्ट से जुड़े होते हैं. android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID, रॉ कॉन्टैक्ट के लिए _ID वैल्यू से लिंक करता है. रॉ कॉन्टैक्ट का खाता टाइप और खाते का नाम भी स्ट्रीम आइटम की लाइन में सेव किया जाता है.
अपनी स्ट्रीम के डेटा को इन कॉलम में सेव करें:
- android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE
- ज़रूरी है. इस स्ट्रीम आइटम से जुड़े रॉ कॉन्टैक्ट के लिए, उपयोगकर्ता का खाता टाइप. कोई स्ट्रीम आइटम डालते समय, इस वैल्यू को सेट करना न भूलें.
- android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME
- ज़रूरी है. इस स्ट्रीम आइटम से जुड़े रॉ कॉन्टैक्ट के लिए, उपयोगकर्ता के खाते का नाम. कोई स्ट्रीम आइटम डालते समय, इस वैल्यू को सेट करना न भूलें.
- आइडेंटिफ़ायर कॉलम
-
ज़रूरी है. स्ट्रीम आइटम डालते समय, आपको ये आइडेंटिफ़ायर कॉलम डालने होंगे:
- android.provider.ContactsContract.StreamItemsColumns#CONTACT_ID: उस संपर्क की android.provider.BaseColumns#_ID वैल्यू जिससे यह स्ट्रीम आइटम जुड़ा है.
- android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY: android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY की वैल्यू, उस संपर्क की वैल्यू होती है जिससे यह स्ट्रीम आइटम जुड़ा होता है.
- android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID: रॉ कॉन्टैक्ट की android.provider.BaseColumns#_ID वैल्यू, जिससे यह स्ट्रीम आइटम जुड़ा है.
- android.provider.ContactsContract.StreamItemsColumns#COMMENTS
- ज़रूरी नहीं. स्टोर की खास जानकारी, जिसे स्ट्रीम आइटम की शुरुआत में दिखाया जा सकता है.
- android.provider.ContactsContract.StreamItemsColumns#TEXT
-
स्ट्रीम आइटम का टेक्स्ट, आइटम के सोर्स से पोस्ट किया गया कॉन्टेंट या स्ट्रीम आइटम जनरेट करने वाली किसी कार्रवाई का ब्यौरा. इस कॉलम में, कोई भी फ़ॉर्मैटिंग और एम्बेड की गई रिसॉर्स इमेज शामिल हो सकती हैं. इन्हें
fromHtml()रेंडर कर सकता है. सेवा देने वाली कंपनी, लंबे कॉन्टेंट को छोटा कर सकती है या उसमें एलिप्सिस (तीन बिंदु) जोड़ सकती है. हालांकि, वह टैग को तोड़ने से बचने की कोशिश करेगी. - android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP
- एक टेक्स्ट स्ट्रिंग, जिसमें स्ट्रीम आइटम को शामिल करने या अपडेट करने का समय शामिल होता है. यह समय, epoch के बाद से मिलीसेकंड के फ़ॉर्मैट में होता है. स्ट्रीम आइटम डालने या अपडेट करने वाले ऐप्लिकेशन, इस कॉलम को मैनेज करने के लिए ज़िम्मेदार होते हैं. संपर्क सूची इसे अपने-आप मैनेज नहीं करती.
अपने स्ट्रीम आइटम की पहचान करने वाली जानकारी दिखाने के लिए, android.provider.ContactsContract.StreamItemsColumns#RES_ICON, android.provider.ContactsContract.StreamItemsColumns#RES_LABEL, और android.provider.ContactsContract.StreamItemsColumns#RES_PACKAGE का इस्तेमाल करके, अपने ऐप्लिकेशन में मौजूद संसाधनों को लिंक करें.
android.provider.ContactsContract.StreamItems टेबल में, android.provider.ContactsContract.StreamItemsColumns#SYNC1 से लेकर android.provider.ContactsContract.StreamItemsColumns#SYNC4 तक के कॉलम भी शामिल होते हैं. इनका इस्तेमाल सिर्फ़ सिंक अडैप्टर करते हैं.
सोशल स्ट्रीम फ़ोटो
android.provider.ContactsContract.StreamItemPhotos टेबल में, स्ट्रीम आइटम से जुड़ी फ़ोटो सेव होती हैं. टेबल का
android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID कॉलम,
android.provider.ContactsContract.StreamItems टेबल के
_ID कॉलम की वैल्यू से लिंक होता है. फ़ोटो के रेफ़रंस, टेबल में इन कॉलम में सेव किए जाते हैं:
- android.provider.ContactsContract.StreamItemPhotos#PHOTO कॉलम (एक BLOB).
- फ़ोटो का बाइनरी वर्शन. सेवा देने वाली कंपनी ने इसे सेव करने और दिखाने के लिए, इसका साइज़ बदला है. यह कॉलम, संपर्क सूची के पिछले वर्शन के साथ काम करने की सुविधा के लिए उपलब्ध है. इस कॉलम का इस्तेमाल, फ़ोटो सेव करने के लिए किया जाता था. हालांकि, मौजूदा वर्शन में आपको फ़ोटो सेव करने के लिए इस कॉलम का इस्तेमाल नहीं करना चाहिए. इसके बजाय, फ़ोटो को किसी फ़ाइल में सेव करने के लिए, android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID या android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI का इस्तेमाल करें. इन दोनों के बारे में यहां बताया गया है. इस कॉलम में अब फ़ोटो का थंबनेल मौजूद है, जिसे पढ़ा जा सकता है.
- android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID
-
रॉ कॉन्टैक्ट की फ़ोटो का न्यूमेरिक आइडेंटिफ़ायर. इस वैल्यू को कॉन्स्टेंट
DisplayPhoto.CONTENT_URIमें जोड़ें, ताकि आपको किसी एक फ़ोटो फ़ाइल पर ले जाने वाला कॉन्टेंट यूआरआई मिल सके. इसके बाद, फ़ोटो फ़ाइल का हैंडल पाने के लिएopenAssetFileDescriptor()को कॉल करें. - android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI
-
एक कॉन्टेंट यूआरआई, जो सीधे तौर पर इस लाइन में मौजूद फ़ोटो की फ़ाइल पर ले जाता है.
फ़ोटो फ़ाइल का हैंडल पाने के लिए, इस यूआरआई के साथ
openAssetFileDescriptor()को कॉल करें.
सोशल स्ट्रीम टेबल का इस्तेमाल करना
ये टेबल, संपर्क सूची की अन्य मुख्य टेबल की तरह ही काम करती हैं. हालांकि, इनमें ये अंतर होते हैं:
- इन टेबल को ऐक्सेस करने के लिए, अतिरिक्त अनुमतियों की ज़रूरत होती है. इनसे डेटा पढ़ने के लिए, आपके ऐप्लिकेशन के पास android.Manifest.permission#READ_SOCIAL_STREAM की अनुमति होनी चाहिए. इनमें बदलाव करने के लिए, आपके ऐप्लिकेशन के पास android.Manifest.permission#WRITE_SOCIAL_STREAM की अनुमति होनी चाहिए.
-
android.provider.ContactsContract.StreamItems टेबल के लिए, हर रॉ कॉन्टैक्ट के लिए सेव की गई लाइनों की संख्या सीमित होती है. इस सीमा तक पहुंचने के बाद, संपर्क सूची नए स्ट्रीम आइटम की पंक्तियों के लिए जगह बनाती है. इसके लिए, वह सबसे पुराने android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP वाली पंक्तियों को अपने-आप मिटा देती है. सीमा की जानकारी पाने के लिए, कॉन्टेंट यूआरआई android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI पर क्वेरी करें. कॉन्टेंट यूआरआई को
nullपर सेट करने के अलावा, अन्य सभी आर्ग्युमेंट को छोड़ा जा सकता है. क्वेरी, एक पंक्ति वाला कर्सर दिखाती है. इसमें एक कॉलम android.provider.ContactsContract.StreamItems#MAX_ITEMS होता है.
android.provider.ContactsContract.StreamItems.StreamItemPhotos क्लास, android.provider.ContactsContract.StreamItemPhotos की सब-टेबल तय करती है. इसमें किसी एक स्ट्रीम आइटम के लिए, फ़ोटो की लाइनें होती हैं.
सोशल स्ट्रीम इंटरैक्शन
संपर्क सूची, सोशल स्ट्रीम के डेटा को मैनेज करती है. यह डेटा, डिवाइस के संपर्क ऐप्लिकेशन के साथ मिलकर, आपके सोशल नेटवर्किंग सिस्टम को मौजूदा संपर्कों से जोड़ने का एक बेहतरीन तरीका उपलब्ध कराता है. ये सुविधाएं उपलब्ध हैं:
- सिंक अडैप्टर की मदद से, सोशल नेटवर्किंग सेवा को संपर्क सूची से सिंक करके, किसी उपयोगकर्ता के संपर्कों की हाल ही की गतिविधि को वापस पाया जा सकता है. साथ ही, उसे android.provider.ContactsContract.StreamItems और android.provider.ContactsContract.StreamItemPhotos टेबल में सेव किया जा सकता है, ताकि बाद में इस्तेमाल किया जा सके.
- नियमित तौर पर सिंक करने के अलावा, सिंक अडैप्टर को ट्रिगर करके, अतिरिक्त डेटा हासिल किया जा सकता है. ऐसा तब होता है, जब उपयोगकर्ता किसी संपर्क को देखने के लिए चुनता है. इससे आपका सिंक अडैप्टर, संपर्क के लिए हाई रिज़ॉल्यूशन वाली फ़ोटो और हाल ही के स्ट्रीम आइटम को वापस पा सकता है.
- डिवाइस के संपर्क ऐप्लिकेशन और संपर्क सूची में सूचना रजिस्टर करके, संपर्क देखे जाने पर इंटेंट पाया जा सकता है. साथ ही, उस समय अपनी सेवा से संपर्क की स्थिति अपडेट की जा सकती है. यह तरीका, सिंक अडैप्टर की मदद से पूरी तरह से सिंक करने की तुलना में ज़्यादा तेज़ हो सकता है. साथ ही, इसमें कम बैंडविड्थ का इस्तेमाल हो सकता है.
- उपयोगकर्ता, डिवाइस के संपर्क ऐप्लिकेशन में संपर्क देखते समय, आपकी सोशल नेटवर्किंग सेवा में कोई संपर्क जोड़ सकते हैं. इसे "संपर्क को न्योता दें" सुविधा की मदद से चालू किया जा सकता है. इसके लिए, आपको ऐसी गतिविधि करनी होगी जिससे आपके नेटवर्क में कोई मौजूदा संपर्क जुड़ जाए. साथ ही, आपको एक एक्सएमएल फ़ाइल की ज़रूरत होगी, जो डिवाइस के संपर्क ऐप्लिकेशन और संपर्क सूची को आपके ऐप्लिकेशन की जानकारी उपलब्ध कराती है.
संपर्क सूची के साथ स्ट्रीम आइटम का नियमित सिंक, अन्य सिंक की तरह ही होता है. सिंक करने के बारे में ज़्यादा जानने के लिए, संपर्क सूची के सिंक अडैप्टर सेक्शन देखें. सूचनाएं रजिस्टर करने और संपर्कों को न्योता भेजने के बारे में, अगले दो सेक्शन में बताया गया है.
सोशल नेटवर्किंग व्यू मैनेज करने के लिए रजिस्टर करना
जब उपयोगकर्ता आपके सिंक अडैप्टर से मैनेज किए जा रहे किसी संपर्क को देखता है, तब सूचनाएं पाने के लिए अपने सिंक अडैप्टर को रजिस्टर करें:
-
अपने प्रोजेक्ट की
res/xml/डायरेक्ट्री में,contacts.xmlनाम की फ़ाइल बनाएं. अगर आपके पास पहले से ही यह फ़ाइल है, तो इस चरण को छोड़ा जा सकता है. -
इस फ़ाइल में,
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">एलिमेंट जोड़ें. अगर यह एलिमेंट पहले से मौजूद है, तो इस चरण को छोड़ा जा सकता है. -
ऐसी सेवा को रजिस्टर करने के लिए जिसे उपयोगकर्ता के डिवाइस के संपर्क ऐप्लिकेशन में, किसी संपर्क की ज़्यादा जानकारी वाला पेज खोलने पर सूचना मिलती है, एलिमेंट में एट्रिब्यूट
viewContactNotifyService="serviceclass"जोड़ें. यहांserviceclass, सेवा का पूरी तरह से क्वालिफ़ाइड क्लासनेम है. इसे डिवाइस के संपर्क ऐप्लिकेशन से इंटेंट मिलना चाहिए. सूचना देने वाली सेवा के लिए, ऐसी क्लास का इस्तेमाल करें जोIntentServiceको एक्सटेंड करती हो. इससे सेवा को इंटेंट मिल सकेंगे. इनकमिंग इंटेंट के डेटा में, उस रॉ कॉन्टैक्ट का कॉन्टेंट यूआरआई शामिल होता है जिस पर उपयोगकर्ता ने क्लिक किया है. सूचना देने वाली सेवा से, रॉ कॉन्टैक्ट का डेटा अपडेट करने के लिए, सिंक अडैप्टर को बाइंड किया जा सकता है और फिर उसे कॉल किया जा सकता है.
जब उपयोगकर्ता किसी स्ट्रीम आइटम या फ़ोटो या दोनों पर क्लिक करे, तो कॉल की जाने वाली गतिविधि को रजिस्टर करने के लिए:
-
अपने प्रोजेक्ट की
res/xml/डायरेक्ट्री में,contacts.xmlनाम की फ़ाइल बनाएं. अगर आपके पास पहले से ही यह फ़ाइल है, तो इस चरण को छोड़ा जा सकता है. -
इस फ़ाइल में,
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">एलिमेंट जोड़ें. अगर यह एलिमेंट पहले से मौजूद है, तो इस चरण को छोड़ा जा सकता है. -
डिवाइस के संपर्क ऐप्लिकेशन में मौजूद स्ट्रीम आइटम पर उपयोगकर्ता के क्लिक को मैनेज करने के लिए, अपनी किसी गतिविधि को रजिस्टर करें. इसके लिए, एलिमेंट में
viewStreamItemActivity="activityclass"एट्रिब्यूट जोड़ें. यहांactivityclass, उस गतिविधि का पूरी तरह से क्वालिफ़ाइड क्लासनेम है जिसे डिवाइस के संपर्क ऐप्लिकेशन से इंटेंट मिलना चाहिए. -
डिवाइस के संपर्क ऐप्लिकेशन में मौजूद स्ट्रीम फ़ोटो पर उपयोगकर्ता के क्लिक को मैनेज करने के लिए, अपनी किसी गतिविधि को रजिस्टर करें. इसके लिए, एलिमेंट में एट्रिब्यूट
viewStreamItemPhotoActivity="activityclass"जोड़ें. यहांactivityclass, उस गतिविधि का पूरी तरह से क्वालिफ़ाइड क्लासनेम है जिसे डिवाइस के संपर्क ऐप्लिकेशन से इंटेंट मिलना चाहिए.
<ContactsAccountType> एलिमेंट के बारे में ज़्यादा जानकारी, <ContactsAccountType> एलिमेंट सेक्शन में दी गई है.
इनकमिंग इंटेंट में, उस आइटम या फ़ोटो का कॉन्टेंट यूआरआई शामिल होता है जिस पर उपयोगकर्ता ने क्लिक किया है. टेक्स्ट आइटम और फ़ोटो के लिए अलग-अलग गतिविधियां दिखाने के लिए, एक ही फ़ाइल में दोनों एट्रिब्यूट का इस्तेमाल करें.
आपकी सोशल नेटवर्किंग सेवा के साथ इंटरैक्ट करना
उपयोगकर्ताओं को आपकी सोशल नेटवर्किंग साइट पर किसी संपर्क को न्योता देने के लिए, डिवाइस के संपर्क ऐप्लिकेशन को छोड़ने की ज़रूरत नहीं है. इसके बजाय, डिवाइस के संपर्क ऐप्लिकेशन से, संपर्क को आपकी किसी गतिविधि में शामिल होने का न्योता भेजने के लिए इंटेंट भेजा जा सकता है. इसका सेट अप करने के लिए:
-
अपने प्रोजेक्ट की
res/xml/डायरेक्ट्री में,contacts.xmlनाम की फ़ाइल बनाएं. अगर आपके पास पहले से ही यह फ़ाइल है, तो इस चरण को छोड़ा जा सकता है. -
इस फ़ाइल में,
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">एलिमेंट जोड़ें. अगर यह एलिमेंट पहले से मौजूद है, तो इस चरण को छोड़ा जा सकता है. -
ये एट्रिब्यूट जोड़ें:
inviteContactActivity="activityclass"-
inviteContactActionLabel="@string/invite_action_label"
activityclassवैल्यू, उस गतिविधि का पूरी तरह क्वालिफ़ाइड क्लासनेम है जिसे इंटेंट मिलना चाहिए.invite_action_labelवैल्यू एक टेक्स्ट स्ट्रिंग है, जो डिवाइस के संपर्क ऐप्लिकेशन में कनेक्शन जोड़ें मेन्यू में दिखती है.
ध्यान दें: ContactsSource, ContactsAccountType के लिए इस्तेमाल किया जाने वाला एक पुराना टैग नाम है.
contacts.xml रेफ़रंस
contacts.xml फ़ाइल में एक्सएमएल एलिमेंट होते हैं. ये एलिमेंट, संपर्क ऐप्लिकेशन और संपर्क सूची के साथ आपके सिंक अडैप्टर और ऐप्लिकेशन के इंटरैक्शन को कंट्रोल करते हैं. इन एलिमेंट के बारे में, नीचे दिए गए सेक्शन में बताया गया है.
<ContactsAccountType> एलिमेंट
<ContactsAccountType> एलिमेंट, संपर्क ऐप्लिकेशन के साथ आपके ऐप्लिकेशन के इंटरैक्शन को कंट्रोल करता है. इसका सिंटैक्स इस तरह है:
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android" inviteContactActivity="activity_name" inviteContactActionLabel="invite_command_text" viewContactNotifyService="view_notify_service" viewGroupActivity="group_view_activity" viewGroupActionLabel="group_action_text" viewStreamItemActivity="viewstream_activity_name" viewStreamItemPhotoActivity="viewphotostream_activity_name">
इसमें शामिल है:
res/xml/contacts.xml
में ये शामिल हो सकते हैं:
<ContactsDataKind>
ब्यौरा:
यह Android कॉम्पोनेंट और यूज़र इंटरफ़ेस (यूआई) लेबल के बारे में बताता है. इनकी मदद से, उपयोगकर्ता अपने किसी संपर्क को सोशल नेटवर्क पर जुड़ने का न्योता भेज सकते हैं. साथ ही, सोशल नेटवर्क की किसी स्ट्रीम के अपडेट होने पर, उपयोगकर्ताओं को सूचना दी जा सकती है. इसके अलावा, और भी कई काम किए जा सकते हैं.
ध्यान दें कि <ContactsAccountType> के एट्रिब्यूट के लिए, एट्रिब्यूट प्रीफ़िक्स android: ज़रूरी नहीं है.
एट्रिब्यूट:
inviteContactActivity- आपके ऐप्लिकेशन में मौजूद उस गतिविधि की क्लास का पूरा नाम जिसे आपको तब चालू करना है, जब उपयोगकर्ता डिवाइस के संपर्क ऐप्लिकेशन से कनेक्शन जोड़ें को चुनता है.
inviteContactActionLabel-
कनेक्शन जोड़ें मेन्यू में,
inviteContactActivityमें बताई गई गतिविधि के लिए दिखने वाली टेक्स्ट स्ट्रिंग. उदाहरण के लिए, "मेरे नेटवर्क में फ़ॉलो करें" स्ट्रिंग का इस्तेमाल किया जा सकता है. इस लेबल के लिए, स्ट्रिंग रिसॉर्स आइडेंटिफ़ायर का इस्तेमाल किया जा सकता है. viewContactNotifyService- आपके ऐप्लिकेशन में मौजूद किसी सेवा का पूरी तरह से क्वालिफ़ाइड क्लास नेम. जब उपयोगकर्ता किसी संपर्क को देखता है, तो इस सेवा को सूचनाएं मिलनी चाहिए. यह सूचना, डिवाइस के संपर्क ऐप्लिकेशन से भेजी जाती है. इससे आपके ऐप्लिकेशन को, डेटा खर्च करने वाली कार्रवाइयों को तब तक रोकने की अनुमति मिलती है, जब तक उनकी ज़रूरत न हो. उदाहरण के लिए, आपका ऐप्लिकेशन इस सूचना का जवाब देने के लिए, संपर्क की हाई रिज़ॉल्यूशन वाली फ़ोटो और हाल ही के सोशल स्ट्रीम आइटम को पढ़ सकता है और दिखा सकता है. इस सुविधा के बारे में ज़्यादा जानकारी, सोशल स्ट्रीम इंटरैक्शन सेक्शन में दी गई है.
viewGroupActivity- आपके ऐप्लिकेशन में मौजूद किसी गतिविधि की क्लास का पूरी तरह क्वालिफ़ाइड नाम, जो ग्रुप की जानकारी दिखा सकता है. जब उपयोगकर्ता डिवाइस के संपर्क ऐप्लिकेशन में ग्रुप लेबल पर क्लिक करता है, तो इस गतिविधि के लिए यूज़र इंटरफ़ेस (यूआई) दिखता है.
viewGroupActionLabel-
संपर्क ऐप्लिकेशन, यूज़र इंटरफ़ेस (यूआई) कंट्रोल के लिए यह लेबल दिखाता है. इससे उपयोगकर्ता, आपके ऐप्लिकेशन में ग्रुप देख सकता है.
इस एट्रिब्यूट के लिए, स्ट्रिंग रिसॉर्स आइडेंटिफ़ायर का इस्तेमाल किया जा सकता है.
viewStreamItemActivity- आपके ऐप्लिकेशन में मौजूद किसी गतिविधि का पूरी तरह से क्वालिफ़ाइड क्लास नेम. इसे डिवाइस का संपर्क ऐप्लिकेशन तब लॉन्च करता है, जब उपयोगकर्ता किसी रॉ कॉन्टैक्ट के लिए स्ट्रीम आइटम पर क्लिक करता है.
viewStreamItemPhotoActivity- आपके ऐप्लिकेशन में मौजूद किसी गतिविधि की क्लास का पूरा नाम. इसे डिवाइस का संपर्क ऐप्लिकेशन तब लॉन्च करता है, जब उपयोगकर्ता किसी रॉ कॉन्टैक्ट के लिए, स्ट्रीम आइटम में मौजूद फ़ोटो पर क्लिक करता है.
<ContactsDataKind> एलिमेंट
<ContactsDataKind> एलिमेंट, संपर्क ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) में आपके ऐप्लिकेशन की कस्टम डेटा लाइनों को कंट्रोल करता है. इसका सिंटैक्स इस तरह है:
<ContactsDataKind android:mimeType="MIMEtype" android:icon="icon_resources" android:summaryColumn="column_name" android:detailColumn="column_name">
इसमें शामिल है:
<ContactsAccountType>
ब्यौरा:
इस एलिमेंट का इस्तेमाल करके, संपर्क ऐप्लिकेशन को रॉ कॉन्टैक्ट की जानकारी के हिस्से के तौर पर, कस्टम डेटा की लाइन का कॉन्टेंट दिखाने की अनुमति दी जा सकती है. <ContactsAccountType> का हर <ContactsDataKind> चाइल्ड एलिमेंट, कस्टम डेटा की लाइन के टाइप को दिखाता है. इसे आपका सिंक अडैप्टर, ContactsContract.Data टेबल में जोड़ता है. इस्तेमाल किए जाने वाले हर कस्टम एमआईएमई टाइप के लिए, एक <ContactsDataKind> एलिमेंट जोड़ें. अगर आपके पास कस्टम डेटा की ऐसी लाइन है जिसके लिए आपको डेटा नहीं दिखाना है, तो आपको एलिमेंट जोड़ने की ज़रूरत नहीं है.
एट्रिब्यूट:
android:mimeType-
ContactsContract.Dataटेबल में, कस्टम डेटा की लाइन के किसी टाइप के लिए तय किया गया कस्टम एमआईएमई टाइप. उदाहरण के लिए, वैल्यूvnd.android.cursor.item/vnd.example.locationstatus, डेटा की उस लाइन के लिए कस्टम एमआईएमई टाइप हो सकती है जो किसी संपर्क की पिछली जगह की जानकारी रिकॉर्ड करती है. android:icon- Android का ड्रॉ करने लायक संसाधन जिसे संपर्क ऐप्लिकेशन, आपके डेटा के बगल में दिखाता है. इसका इस्तेमाल करके, उपयोगकर्ता को बताएं कि डेटा आपकी सेवा से मिला है.
android:summaryColumn- डेटा लाइन से मिली दो वैल्यू में से पहली वैल्यू के लिए कॉलम का नाम. इस डेटा लाइन की एंट्री की पहली लाइन के तौर पर, वैल्यू दिखती है. पहली लाइन का इस्तेमाल, डेटा की खास जानकारी के तौर पर किया जाता है. हालांकि, ऐसा करना ज़रूरी नहीं है. android:detailColumn भी देखें.
android:detailColumn-
डेटा लाइन से मिली दो वैल्यू में से दूसरी वैल्यू के लिए कॉलम का नाम. यह वैल्यू, इस डेटा लाइन की एंट्री की दूसरी लाइन के तौर पर दिखती है.
android:summaryColumnभी देखें.
संपर्क सूची की अन्य सुविधाएं
पिछले सेक्शन में बताई गई मुख्य सुविधाओं के अलावा, संपर्क सूची में संपर्कों के डेटा के साथ काम करने के लिए, ये काम की सुविधाएं भी मिलती हैं:
- संपर्क ग्रुप
- फ़ोटो को बेहतर बनाने के लिए सुविधाएं
संपर्क ग्रुप
संपर्क सूची, मिलते-जुलते संपर्कों के कलेक्शन को ग्रुप डेटा के साथ लेबल कर सकती है. हालांकि, ऐसा करना ज़रूरी नहीं है. अगर उपयोगकर्ता खाते से जुड़ा सर्वर, ग्रुप को मैनेज करना चाहता है, तो खाते के टाइप के लिए सिंक अडैप्टर को संपर्क सूची और सर्वर के बीच ग्रुप का डेटा ट्रांसफ़र करना चाहिए. जब उपयोगकर्ता सर्वर में कोई नया संपर्क जोड़ते हैं और फिर इस संपर्क को किसी नए ग्रुप में डालते हैं, तो सिंक अडैप्टर को ContactsContract.Groups टेबल में नया ग्रुप जोड़ना होगा. रॉ कॉन्टैक्ट जिस ग्रुप या जिन ग्रुप से जुड़ा होता है उन्हें ContactsContract.Data टेबल में सेव किया जाता है. इसके लिए, ContactsContract.CommonDataKinds.GroupMembership एमआईएमई टाइप का इस्तेमाल किया जाता है.
अगर आपको ऐसा सिंक अडैप्टर डिज़ाइन करना है जो सर्वर से संपर्क सूची में रॉ कॉन्टैक्ट डेटा जोड़ेगा और ग्रुप का इस्तेमाल नहीं किया जा रहा है, तो आपको संपर्क सूची को बताना होगा कि वह आपका डेटा दिखाए. जब कोई उपयोगकर्ता डिवाइस में कोई खाता जोड़ता है, तब उस कोड में ContactsContract.Settings पंक्ति को अपडेट करें जिसे संपर्क सूची, खाते के लिए जोड़ती है. इस लाइन में, Settings.UNGROUPED_VISIBLE कॉलम की वैल्यू को 1 पर सेट करें. ऐसा करने पर, संपर्क सूची हमेशा आपके संपर्कों का डेटा दिखाएगी. भले ही, आपने ग्रुप का इस्तेमाल न किया हो.
संपर्क की फ़ोटो
ContactsContract.Data टेबल में, फ़ोटो को Photo.CONTENT_ITEM_TYPE एमआईएमई टाइप वाली पंक्तियों के तौर पर सेव किया जाता है. पंक्ति का
CONTACT_ID कॉलम, रॉ कॉन्टैक्ट के
_ID कॉलम से लिंक होता है.
ContactsContract.Contacts.Photo क्लास, ContactsContract.Contacts की एक सब-टेबल तय करती है. इसमें किसी संपर्क की मुख्य फ़ोटो की जानकारी होती है. यह संपर्क के मुख्य रॉ कॉन्टैक्ट की मुख्य फ़ोटो होती है. इसी तरह,
ContactsContract.RawContacts.DisplayPhoto क्लास, ContactsContract.RawContacts की एक सब-टेबल को तय करती है.
इसमें रॉ कॉन्टैक्ट की मुख्य फ़ोटो की जानकारी होती है.
ContactsContract.Contacts.Photo और ContactsContract.RawContacts.DisplayPhoto के रेफ़रंस दस्तावेज़ में, फ़ोटो की जानकारी को वापस पाने के उदाहरण शामिल हैं. रॉ कॉन्टैक्ट के लिए मुख्य थंबनेल को वापस पाने के लिए, कोई सुविधाजनक क्लास नहीं है. हालांकि, रॉ कॉन्टैक्ट की मुख्य फ़ोटो वाली लाइन ढूंढने के लिए, ContactsContract.Data टेबल में क्वेरी भेजी जा सकती है. इसके लिए, रॉ कॉन्टैक्ट के _ID, Photo.CONTENT_ITEM_TYPE, और IS_PRIMARY कॉलम को चुनें.
किसी व्यक्ति के सोशल स्ट्रीम डेटा में फ़ोटो भी शामिल हो सकती हैं. ये android.provider.ContactsContract.StreamItemPhotos टेबल में सेव किए जाते हैं. इसके बारे में ज़्यादा जानकारी, सोशल स्ट्रीम फ़ोटो सेक्शन में दी गई है.