2012-04-16 20 views
14

में 1 परिवर्तन के बाद दो बार बुलाया गया है मेरे पास एक ऐप है जिसमें मैं एंड्रॉइड संपर्क सूची में दूरस्थ सर्वर पर विवरण भेजने की उम्मीद कर रहा हूं, ताकि उपयोगकर्ता अपने संपर्क ऑनलाइन देख सके। ऐसा करने के लिए मैं संपर्क सूची में फोन पर किए गए किसी भी बदलाव के दूरस्थ सर्वर को सूचित करना चाहता हूं।सामग्री पर्यवेक्षक ऑन चेंज विधि कर्सर

मैंने एक सेवा से 'ContentContract.Contacts.CONTENT_URI' पर एक सामग्री ऑब्सर्वर स्थापित किया है जो फोन बूट होने पर शुरू हो जाता है।

मेरे पास कई प्रश्नोत्तरी हैं, पहला 2 आकस्मिक है, तीसरा मेरी प्रमुख चिंता है।

1: एक बार जब मैंने एक सेवा स्थापित की है जो मेरे कर्सर पर एक ContentObserver पंजीकृत करता है, तो क्या यह पर्यवेक्षक केवल सेवा के भीतर मौजूद है? मेरा मतलब है, अगर सेवा मारे जाती है, तो क्या सामग्री ऑब्सर्वर का पालन करना जारी रखता है?

2: मुझे संदेह है कि उत्तर नहीं है, लेकिन मैं वैसे भी पूछूंगा। क्या यह जानने का कोई तरीका है कि कौन सा संपर्क अपडेट किया जा रहा है मेरी सामग्री ऑब्सर्वर की विनिमय विधि को ट्रिगर कर रहा है? वर्तमान में मुझे फोन पर सभी तह संपर्कों की सूची संकलित करना है और उन्हें अपने रिमोट सर्वर पर भेजना है, यह अपडेट किए जा रहे संपर्कों का विवरण भेजने के लिए इतना आसान होगा।

3: यह मेरा मुख्य प्रश्न है, जब मैं अपनी संपर्क सूची में बदलाव करता हूं तो त्वरित उत्तराधिकार में ऑन चेंज विधि को दो बार निकाल दिया जा रहा है। 1 परिवर्तन, 2 कॉल। क्या इसका प्रबंधन करने के लिए वैसे भी है? मेरी Logcat में 2 त्वरित लाइनों में

public class ContactService extends Service { 

    JSONArray contactList; 

    @Override 
    public IBinder onBind(Intent arg0) { 
     return null; 
    } 

    @Override 
    public void onCreate() { 
     Log.i("C2DM","content observers initialised"); 
     super.onCreate(); 



     //Call Log Content Provider observer 

     MyContentContactsObserver contactsObserver = new MyContentContactsObserver(); 
     ContactService.this.getContentResolver().registerContentObserver (ContactsContract.Contacts.CONTENT_URI, true, contactsObserver); 

    } 

    private class MyContentContactsObserver extends ContentObserver { 

     public MyContentContactsObserver() { 
      super(null); 
     } 

     @Override 
     public void onChange(boolean selfChange) { 
      super.onChange(selfChange);  
      Log.i("LOG","detected change in contacts: "+selfChange); 
     } 
    } 
} 

परिणाम:

detected change in contacts: false 
detected change in contacts: false 

उत्तर

29

मैं एक ऐसी ही कार्यान्वयन किया था और कैलेंडर के ईवेंट URI पर एक ContentObserver निर्धारित किया था। और मुझे सभी समस्याओं का सामना करना पड़ा, अब आप सामना कर रहे हैं। तो मेरी समाधान/सुझावों के साथ अपने प्रश्न यहाँ जाता है ....

1) एक बार मैं एक सेवा है जो मेरी कर्सर पर एक ContentObserver पंजीकृत करता है की स्थापना की है, कि पर्यवेक्षक केवल सेवा के भीतर मौजूद है? मेरा मतलब है, अगर सेवा मारे गए हैं, सामग्री ऑब्सर्वर का पालन करना जारी रखता है?

नहीं, यह यूआरआई पर आपकी सामग्री को सामग्री का पालन नहीं करेगा। लेकिन इसका समाधान है। आप हमेशा एक चल रही सेवा बना सकते हैं। कुछ मेमोरी समस्या या अन्य अप्रत्याशित बर्खास्तगी के कारण यह सेवा फिर से बनाई जाएगी जैसे ही इसे खारिज कर दिया जाएगा। जब तक इसे स्पष्ट रूप से खारिज नहीं किया जाता है तब तक यह हमेशा जारी रहेगा। ऐसी सेवा बनाने के लिए अपनी सेवा कक्षा में OnStartCommand(Intent intent, int flags, final int startId) ओवरराइड करें और START_STICKY लौटाएं। नीचे दिए गए कोड पर एक नज़र डालें।

public int onStartCommand(Intent intent, int flags, final int startId) { 

    String authenticationKey = ((MainApplication) getApplicationContext()).getDbConnector().getUserAuthDefault() ; 
    // if user is not registered yet, stop this service, it may be called from boot reciever. 
    if(authenticationKey == null){ 
     stopSelf(); 
    } 

    // restart, if we get killed. 
    return START_STICKY; 
} 

2: मुझे संदेह है कि उत्तर नहीं है, लेकिन मैं वैसे भी पूछूंगा। क्या है जो जानने के लिए अपडेट किया जा रहा संपर्क मेरी सामग्री ऑब्सर्वर की विनिमय विधि को ट्रिगर कर रहा है? वर्तमान में मुझे फोन पर सभी तह संपर्कों की सूची संकलित करना है और उन्हें अपने रिमोट सर्वर पर पर भेजना है, यह अपडेट किए जा रहे संपर्कों का विवरण भेजने के लिए इतना आसान होगा।

आपने फिर से यह सही अनुमान लगाया। :)। जवाब न है।
विशेष रूप से यह जानने का कोई तरीका नहीं है कि कौन सा संपर्क अपडेट किया गया है। ContentObserver बस आपको यह बताने के लिए एक ईवेंट प्रदान करता है कि यूरी द्वारा इंगित डेटा में कुछ बदलाव किए गए हैं। लेकिन मुझे लगता है कि आप स्थिति को अक्षमता से संभालने में सक्षम हैं, क्योंकि आप सभी संपर्कों की सूची संकलित कर रहे हैं और उन्हें सर्वर पर वापस भेज रहे हैं।
मैं आपको स्थानीय स्टोरेज में संपर्कों की एक सूची बनाए रखने के लिए सुझाव दूंगा, जो सफलतापूर्वक सर्वर पर भेजे जाते हैं। और अगली बार जब आप contentObserver की onChange() विधि में एक कॉल प्राप्त आप content_URI से सभी contacts लाने, उन्हें पहले से संग्रहीत की सूची के साथ तुलना और सर्वर के लिए केवल अद्यतन संपर्कों भेजें।

3: जब मैं अपने संपर्क सूची onChange विधि जल्दी जल्दी में दो बार गोली चलाई जा रही है में एक परिवर्तन करना यह मेरा मुख्य सवाल है,। 1 परिवर्तन, 2 कॉल। क्या का प्रबंधन करने के लिए वैसे भी है?

हाँ ऐसा होता है, लेकिन मुझे लगता है कि आप गलत इंप्रेशन में हैं। मेरे मामले में यह यादृच्छिक रूप से दो बार या तीन बार या उससे भी अधिक बार आग लगती थी। इसलिए मैंने थ्रेसहोल्ड_टाइम अंतराल सेट किया था। एक समय अंतराल जिसके भीतर ContentObserver फिर से निकाल दिया जाता है, तो मैं इसे संसाधित नहीं करता। मैंने ऐसा कुछ किया ..

long lastTimeofCall = 0L; 
long lastTimeofUpdate = 0L; 
long threshold_time = 10000; 

    /* (non-Javadoc) 
    * @see android.database.ContentObserver#onChange(boolean) 
    */ 
    @Override 
    public void onChange(boolean selfChange) { 
     super.onChange(selfChange); 

     Log.d("content service", "on change called"); 

     lastTimeofCall = System.currentTimeMillis(); 

     if(lastTimeofCall - lastTimeofUpdate > threshold_time){ 

     //write your code to find updated contacts here 

      lastTimeofUpdate = System.currentTimeMillis(); 
     } 

    } 

आशा है कि ये सुझाव/समाधान मदद करेंगे।

+1

+1, क्या सभी मामलों में 10000ms दूसरा काम विफल रहता है, क्या आपने उपयोगकर्ताओं से इस पर कोई प्रतिक्रिया ली है, धन्यवाद? –

+0

मुझे इसके बारे में उपयोगकर्ताओं से कोई प्रतिक्रिया मिली है। मैं कार्यान्वयन का सबसे अच्छा तरीका नहीं कहूंगा लेकिन यह अब के रूप में अच्छा काम कर रहा है।यह एक तरह का पैच है जिसे हमें लागू करना था। –

+0

मैं 'currentTime = System.CurrentTimeMillis() '' if (nextCallTime Kobor42

10

विचार करें कि आप अपने पर्यवेक्षक को कैसे पंजीकृत करते हैं। registerContentObserver का दूसरा तर्क boolean notifyForDescendents है, आपने इसे true पर सेट कर दिया है। इसलिए जब आपको संपर्क संपर्क नहीं किया जाएगा तो आपको अधिसूचित किया जाएगा। संपर्क। कॉन्टैक्टुरआई या इसके किसी भी अवरोधक यूरिस को बदल दिया गया था। ऐसा हो सकता है कि दिए गए आईडी के संपर्क के लिए कुछ ऑपरेशन विशिष्ट संपर्क यूरी और वैश्विक संपर्क यूरी दोनों के लिए अधिसूचना को ट्रिगर करता है - दूसरे तर्क के साथ true आपके पर्यवेक्षक दोनों को देखता है।

एक और बात यह है कि आप विशिष्ट संपर्क आईडी uri - ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId) के लिए सामग्री पर्यवेक्षक पंजीकृत कर सकते हैं। हालांकि इसके पास आपके मुद्दे से कोई लेना देना नहीं है, लेकिन प्रत्येक संपर्क के लिए अलग पर्यवेक्षक को पंजीकृत करना बदसूरत दिखता है;)

एक और सुझाव: हो सकता है कि पर्यवेक्षक को अंतिम क्षेत्र के रूप में रखें, इसे क्रिएट (लेकिन केवल इसे पंजीकृत करें) में फिर से बनाएं।

public class ContactService extends Service { 

    private final ContentObserver contactsObserver = new ContentObserver(null) { 

     @Override 
     public void onChange(boolean selfChange) { 
      super.onChange(selfChange);  
      Log.i("LOG","detected change in contacts: "+selfChange); 

      //your code here 
     } 
    }; 

    @Override 
    public IBinder onBind(Intent arg0) { 
     return null; 
    } 

    @Override 
    public void onCreate() { 

     super.onCreate(); 

     getContentResolver().registerContentObserver(
       ContactsContract.Contacts.CONTENT_URI, true, contactsObserver); 
    } 

    @Override 
    public void onDestroy() { 

     getContentResolver().unregisterContentObserver(contactsObserver); 

     super.onDestroy(); 
    } 
} 
5

अपने एनआर के लिए सही आने के लिए। 3: आपके पर्यवेक्षक को दो कॉल के बीच कितना समय है? मुझे लगता है कि आपके पर्यवेक्षक को संपर्क सिंक की वजह से दो बार बुलाया जाता है, जो डेटाबेस को भी अद्यतन करता है। अर्थात। पहली बार आपका वास्तविक अपडेट है, दूसरी बार जब सिंक समाप्त हो जाता है और उसी सिंक वैल्यू को उसी संपर्क पंक्ति में पंजीकृत करता है।

आप समन्वयन को बंद करें और देखें कि यह अभी भी दो बार कहा जाता हो जाता है सकते हैं?

+0

आह, यह एक अच्छी कॉल है। Ive ने उपरोक्त सलाह के साथ इस मुद्दे के आसपास काम किया है, लेकिन आपका जवाब अच्छी समझ में आता है। –

+0

पूरी तरह से समझ में आता है, कोशिश नहीं की लेकिन समझ में आया .. और क्या होगा यदि यह मामला है? अभी भी मुझे लगता है कि हमें कुछ थ्रेसहोल्ड दृश्य का उपयोग करने की आवश्यकता है .. – Farhan

-1

मेरे स्वयं के कोड में एक ही समस्या का सामना करना पड़ा और पता चला कि मैं रजिस्टर कॉन्टेंट ऑब्सर्वर() दो बार कॉल कर रहा था। यद्यपि यह एक ही यूआरआई के लिए था और उसी कक्षा में मेरे ऑन चेंज (बूलियन स्वचेंज) विधि को परिणामस्वरूप दो बार बुलाया गया था।

0

आपके पास ContactService के दो या दो से अधिक उदाहरण हो सकते हैं, जिनमें से सभी को समान संपर्क पंजीकृत किया गया है। संपर्क। CONTENT_URI।

संबंधित मुद्दे