कॉलिंग requestSync()केवल {खाता, ContentAuthority} जोड़ी पर काम करेगी जो सिस्टम को ज्ञात है। एंड्रॉइड को यह बताने के लिए आपके ऐप को कई चरणों से गुजरने की आवश्यकता है जो आप एक विशिष्ट प्रकार के खाते का उपयोग करके एक विशिष्ट प्रकार की सामग्री को सिंक्रनाइज़ करने में सक्षम हैं। यह AndroidManifest में ऐसा करता है।
1. एंड्रॉइड को सूचित करें कि आपका एप्लिकेशन पैकेज सिंकिंग प्रदान करता है
सबसे पहले, AndroidManifest.xml में, आपको घोषित करना होगा कि आपके पास एक सिंक सेवा है:
<service android:name=".sync.mySyncService" android:exported="true">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/sync_myapp" />
</service>
<service>टैग का नाम विशेषता सिंक से कनेक्ट करने के लिए आपकी कक्षा का नाम है ... मैं एक सेकंड में उससे बात करूंगा।
निर्यात किया गया सच सेट करना इसे अन्य घटकों के लिए दृश्यमान बनाता है (आवश्यकता है तो ContentResolverइसे कॉल कर सकते हैं)।
आशय फ़िल्टर यह एक आशय को सिंक करने का अनुरोध करने देता है। (यह तब Intentहोता है ContentResolverजब आप कॉल करते हैं ContentResolver.requestSync()या संबंधित शेड्यूलिंग तरीके।)
<meta-data>टैग नीचे चर्चा की जाएगी।
2. एंड्रॉइड एक सेवा प्रदान करें जिसका उपयोग आपके सिंक एडेप्टर को खोजने के लिए किया जाता है
तो वर्ग ही ... यहाँ एक उदाहरण है:
public class mySyncService extends Service {
private static mySyncAdapter mSyncAdapter = null;
public SyncService() {
super();
}
@Override
public void onCreate() {
super.onCreate();
if (mSyncAdapter == null) {
mSyncAdapter = new mySyncAdapter(getApplicationContext(), true);
}
}
@Override
public IBinder onBind(Intent arg0) {
return mSyncAdapter.getSyncAdapterBinder();
}
}
आपकी कक्षा का विस्तार होना चाहिए Serviceया उसके किसी उपवर्ग को लागू करना चाहिए, उसे लागू public IBinder onBind(Intent)करना चाहिए और SyncAdapterBinderजब यह कहा जाता है तो वापस लौटना चाहिए ... आपको एक प्रकार का चर चाहिए AbstractThreadedSyncAdapter। तो जैसा कि आप देख सकते हैं, उस वर्ग में यह सब कुछ बहुत ज्यादा है। सेवा प्रदान करने का एकमात्र कारण यह है कि Android के लिए अपनी कक्षा को क्वेरी करने के लिए एक मानक इंटरफ़ेस प्रदान करता है कि आपका क्या SyncAdapterहै।
3. class SyncAdapterवास्तव में सिंक करने के लिए प्रदान करें ।
mySyncAdapter वह स्थान है जहाँ वास्तविक सिंक तर्क स्वयं संग्रहीत होता है। onPerformSync()सिंक करने का समय होने पर इसकी विधि को कॉल किया जाता है। मुझे लगता है कि आपके पास पहले से ही यह जगह है।
4. एक खाता-प्रकार और एक सामग्री प्राधिकरण के बीच एक बंधन स्थापित करें
AndroidManifest पर फिर से पीछे मुड़कर देखें, तो <meta-data>हमारी सेवा में अजीब टैग एक महत्वपूर्ण टुकड़ा है जो एक ContentAuthority और एक खाते के बीच बंधन स्थापित करता है। यह बाह्य रूप से एक और xml फ़ाइल को संदर्भित करता है (इसे आप जो भी पसंद करते हैं, अपने ऐप से प्रासंगिक है।) चलिए सिंक_myapp.xml देखें:
<?xml version="1.0" encoding="utf-8" ?>
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="com.android.contacts"
android:accountType="com.google"
android:userVisible="true" />
ठीक है, तो यह क्या करता है? यह एंड्रॉइड को बताता है कि हमने जो सिंक एडेप्टर परिभाषित किया है (वह वर्ग जिसे <service>टैग के नाम तत्व में कहा गया था, जिसमें टैग शामिल है जो <meta-data>इस फ़ाइल को संदर्भित करता है ...) कॉमन.ओक स्टाइल अकाउंट का उपयोग करके संपर्कों को सिंक करेगा।
आपके सभी कंटेंटअथॉरिटी स्ट्रिंग्स को सभी मैच करना है, और जो आप सिंक कर रहे हैं, उसके साथ मैच करें - यह एक स्ट्रिंग होनी चाहिए जिसे आप परिभाषित करते हैं, यदि आप अपना खुद का डेटाबेस बना रहे हैं, या यदि आप ज्ञात कर रहे हैं, तो आपको कुछ मौजूदा डिवाइस स्ट्रिंग्स का उपयोग करना चाहिए। डेटा प्रकार (जैसे संपर्क या कैलेंडर ईवेंट या आपके पास क्या है।) उपरोक्त ("com.android.contacts") संपर्क प्रकार डेटा (आश्चर्य, आश्चर्य) के लिए ContentAuthority string होना चाहिए।
accountType में उन ज्ञात खाता प्रकारों में से एक का मिलान भी करना होता है जो पहले से ही दर्ज हैं, या इसे आपके द्वारा बनाए जा रहे मेल से मेल खाना है (इसमें आपके सर्वर पर स्थिति प्राप्त करने के लिए AccountAuthenticator का उप-वर्ग बनाना शामिल है ... एक लेख, खुद के बारे में बताएं।) फिर से, "com.google" परिभाषित स्ट्रिंग की पहचान है ... google.com शैली खाता क्रेडेंशियल (फिर, यह एक आश्चर्य नहीं होना चाहिए)।
5. किसी दिए गए खाते / ContentAuthority जोड़ी पर सिंक सक्षम करें
अंत में, सिंक को सक्षम करना होगा। आप अपने ऐप पर जाकर और मिलान खाते के भीतर अपने ऐप के बगल में स्थित चेकबॉक्स को सेट करके कंट्रोल पैनल में अकाउंट्स एंड सिंक पेज में कर सकते हैं। वैकल्पिक रूप से, आप इसे अपने ऐप में कुछ सेटअप कोड में कर सकते हैं:
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
सिंक होने के लिए, आपके खाते / प्राधिकरण की जोड़ी को सिंक करने में सक्षम होना चाहिए (ऊपर की तरह) और सिस्टम पर समग्र वैश्विक सिंक ध्वज सेट होना चाहिए, और डिवाइस में नेटवर्क कनेक्टिविटी होनी चाहिए।
यदि आपका खाता / प्राधिकरण सिंक या वैश्विक सिंक अक्षम है, तो कॉल करने से RequestSync () का प्रभाव पड़ता है - यह एक ध्वज सेट करता है जिसे सिंक का अनुरोध किया गया है, और जैसे ही सिंक सक्षम होता है, वैसे ही प्रदर्शन किया जाएगा।
इसके अलावा, एमजीवी के अनुसार , ContentResolver.SYNC_EXTRAS_MANUALआपके अनुरोध के एक्स्ट्रा बंडल में सही होने के लिए सेटिंगसंकट एंड्रॉइड से एक सिंक को मजबूर करने के लिए कहेंगे, भले ही वैश्विक सिंक बंद हो (यहां आपके उपयोगकर्ता का सम्मान हो!)
अंत में, आप ContentResolver फ़ंक्शंस के साथ एक आवधिक अनुसूचित सिंक को फिर से सेट कर सकते हैं।
6. कई खातों के निहितार्थ पर विचार करें
एक ही प्रकार के एक से अधिक खाते (दो @ gmail.com खाते एक डिवाइस या दो फेसबुक अकाउंट, या दो ट्विटर अकाउंट आदि) पर रखना संभव है।) आपको ऐसा करने के आवेदन के प्रभावों पर विचार करना चाहिए। यदि आपके पास दो खाते हैं, तो आप संभवतः दोनों को एक ही डेटाबेस तालिकाओं में सिंक करने का प्रयास नहीं करना चाहते हैं। शायद आपको यह निर्दिष्ट करने की आवश्यकता है कि एक समय में केवल एक ही सक्रिय हो सकता है, और यदि आप खातों को स्विच करते हैं, तो टेबल को फ्लश करें और फिर से सिंक करें। (एक संपत्ति पृष्ठ के माध्यम से जो यह सवाल करता है कि क्या खाते मौजूद हैं)। हो सकता है कि आप प्रत्येक खाते के लिए एक अलग डेटाबेस बनाएँ, हो सकता है कि अलग-अलग तालिकाएँ, प्रत्येक तालिका में एक प्रमुख स्तंभ हो। सभी आवेदन विशिष्ट और कुछ सोचा के योग्य। ContentResolver.setIsSyncable(Account account, String authority, int syncable)यहां रुचि हो सकती है। setSyncAutomatically()यह नियंत्रित करता है कि खाता / प्राधिकरण जोड़ी की जाँच की जाए या नहींअनियंत्रित , जबकि setIsSyncable()लाइन को अनचेक और ग्रे करने का एक तरीका प्रदान करता है ताकि उपयोगकर्ता इसे चालू न कर सके। आप एक खाते को सिंकेबल और दूसरे को सिंकेबल (डीएसएबल) नहीं कर सकते हैं।
7. ContentResolver.notifyChange () से अवगत रहें
एक मुश्किल बात। ContentResolver.notifyChange()एक फ़ंक्शन है जिसका उपयोग ContentProviderएंड्रॉइड को सूचित करने के लिए किया जाता है कि स्थानीय डेटाबेस को बदल दिया गया है। यह दो कार्य करता है, सबसे पहले, यह अद्यतन करने के लिए उस सामग्री का अनुसरण करने वाले कर्सर का कारण होगा, और बदले में आवश्यक और अमान्य और फिर से तैयार करना ListView, आदि ... यह बहुत जादुई है, डेटाबेस में परिवर्तन होता है और आपके ListViewबस अपडेट स्वचालित रूप से होते हैं। बहुत बढ़िया। इसके अलावा, जब डेटाबेस बदलता है, तो एंड्रॉइड आपके सामान्य शेड्यूल के बाहर भी आपके लिए सिंक का अनुरोध करेगा, ताकि उन परिवर्तनों को डिवाइस से निकाल लिया जाए और जितनी जल्दी हो सके सर्वर से सिंक किया जाए। कमाल भी।
हालांकि एक किनारे का मामला है। यदि आप सर्वर से खींचते हैं, और एक अपडेट को अंदर धकेलते हैं ContentProvider, तो यह कर्तव्यपूर्वक कॉल notifyChange()करेगा और एंड्रॉइड जाएगा, "ओह, डेटाबेस में बदलाव, बेहतर उन्हें सर्वर पर डाल दिया!" (दोह!) अच्छी तरह से लिखे जाने के ContentProvidersलिए कुछ परीक्षण होंगे, यह देखने के लिए कि क्या परिवर्तन नेटवर्क से या उपयोगकर्ता से आया है, और syncToNetworkइस व्यर्थ डबल-सिंक को रोकने के लिए बूलियन ध्वज को झूठा सेट करेगा । यदि आप डेटा को एक में ContentProviderफीड कर रहे हैं, तो आपको यह पता लगाना है कि इस काम को कैसे किया जाए - अन्यथा आप हमेशा दो सिंक करेंगे जब केवल एक की जरूरत हो।
8. खुशी महसूस करो!
एक बार जब आपके पास यह सब xml मेटाडाटा हो जाता है, और सिंक सक्षम हो जाता है, तो एंड्रॉइड को पता चल जाएगा कि आपके लिए सब कुछ कैसे कनेक्ट करना है, और सिंक काम करना शुरू कर देता है। इस बिंदु पर, बहुत सी चीजें जो अच्छी हैं, बस जगह पर क्लिक करेंगी और यह बहुत कुछ जादू जैसा महसूस होगा। का आनंद लें!