2011-09-20 15 views
12

मेरे पास ContentObserver एसएमएस प्राप्त करने और लिखने के लिए कार्यान्वयन है, लेकिन इसे कई बार कहा जाता है।ContentObserver को कई बार क्यों कहा जाता है?

कोड:

public class SMSObserverActivity extends Activity { 
    protected MyContentObserver observer = null; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState){ 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     String url = "content://mms-sms/"; 
     Uri uri = Uri.parse(url); 
     observer = new MyContentObserver(new Handler()); 
     getContentResolver().registerContentObserver(uri, true, observer); 
    } 

    @Override 
    protected void onDestroy(){ 
     super.onDestroy(); 

     getContentResolver().unregisterContentObserver(observer); 
    } 

    class MyContentObserver extends ContentObserver { 
     ContentValues values = new ContentValues(); 
     Handler handler; 

     public MyContentObserver(Handler handler){ 
      super(handler); 
      this.handler = handler; 
     } 

     @Override 
     public boolean deliverSelfNotifications(){ 
      return false; 
     } 


     @Override 
     public void onChange(boolean arg0){ 
      super.onChange(arg0); 

      Log.v("SMS", "Notification on SMS observer"); 
      values.put("status", 5); 
      Message msg = new Message(); 
      msg.obj = "xxxxxxxxxx"; 
      int threadId = 0; 
      handler.sendMessage(msg); 

      Uri uriSMSURI = Uri.parse("content://sms/"); 
      Cursor cur = 
        getContentResolver().query(uriSMSURI, null, null, null, 
          null); 
      cur.moveToNext(); 
      Log.e("sms", cur.getString(4)+" "+cur.getString(11)); 
     } 
    } 
} 

मैनिफ़ेस्ट:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.test" 
    android:versionCode="1" 
    android:versionName="1.0"> 
    <uses-sdk android:minSdkVersion="8" /> 
    <uses-permission android:name="android.permission.READ_SMS"></uses-permission> 
    <uses-permission android:name="android.permission.WRITE_SMS"></uses-permission> 

    <application android:icon="@drawable/icon" android:label="@string/app_name"> 
     <activity android:name=".SMSObserverActivity" 
        android:label="@string/app_name"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

    </application> 
</manifest> 

क्यों इसे कई बार कहा जाता है?

संपादित करें:
यह विचार था कि समस्या unregisterContentObserver गायब होने के कारण होती है, लेकिन इससे कोई फर्क नहीं पड़ता।

+0

क्या तुमने कभी यह पता लगा था कि कोशिश सामग्री पर्यवेक्षक द्वारा कई एसएमएस भेजने से बचने के लिए? –

+0

अभी तक नहीं, मेरे पास अभी तक इसका समय नहीं है, लेकिन उत्तर पर टिप्पणियां पढ़ें और इसे सेवा के साथ आज़माएं। शायद आप इसे काम करेंगे। ;) – CSchulz

+0

यदि सेवा में चलाया जाता है तो समस्या एक जैसी है, मुझे डर है –

उत्तर

11

ऐसा इसलिए हो रहा है क्योंकि आप पूरे एसएमएस डेटाबेस के लिए अपनी सामग्री पर्यवेक्षक पंजीकृत कर रहे हैं। तो डेटाबेस में एक टेबल प्रविष्टि अद्यतन होने पर हर बार आपकी सामग्री पर्यवेक्षक अधिसूचित हो जाती है।

इस मामले में जब एक संदेश भेजा जाता है उदाहरण के लिए लगभग 7 टेबल प्रविष्टियां अपडेट हो जाती हैं ताकि आपकी सामग्री पर्यवेक्षक को 7 बार अधिसूचित किया जा सके।

चूंकि मुझे कोई संदेश भेजा जाता है, तो मुझे केवल दिलचस्पी है क्योंकि मैंने केवल कतारबद्ध संदेशों का पालन किया है और इसका मतलब है कि मेरे पर्यवेक्षक को हमेशा तीन बार अधिसूचित किया जाता है इसलिए मैंने इसके खिलाफ सुरक्षा के लिए कोड लागू किया है।

मल्टी प्राप्तकर्ता या बहु भाग संदेश जैसे कुछ अन्य मुद्दे होने की संभावना है लेकिन मूल बातें अब तक काम करती हैं।

+0

ठीक है मैंने सोचा कि पर्यवेक्षक को केवल प्रति ऑब्जेक्ट के सभी संबंधित अपडेट के लिए एक बार कहा जाता है। मुझे लगता है कि देखने के लिए एक अनूठी आईडी है, कौन सी अधिसूचनाएं एक अद्यतन से संबंधित हैं, है ना? – CSchulz

0

आप अपने पर्यवेक्षक सक्षम केवल जब गतिविधि सक्रिय अवस्था में है करना चाहते हैं, मैं तुम्हें क्रमशः registerContentObserver() और unregisterContentObserver() तरीकों onResume() और onPause() को स्थानांतरित करने के लिए सलाह देते हैं। onDestroy() को आपका एप्लिकेशन बाहर निकलने पर नहीं कहा जा सकता है, लेकिन onPause() होने की गारंटी है।

+0

* गतिविधि * चल रहा है, जब पर्यवेक्षक हमेशा सक्रिय रहेंगे। यह सिर्फ एक अवलोकन सामग्री परीक्षण है। – CSchulz

+0

गतिविधि 'ऑनस्यूम()' और 'ऑन पॉज़()' के बीच चल रही है, दूसरी बार यह पृष्ठभूमि में है या दिखाई नहीं दे रही है। यह 'ऑनड्रॉय()' पर कॉल किए बिना भी मारे जा सकता है, और जब आप 'ऑनक्रेट()' में आवेदन फिर से बनाते हैं, तो आप दूसरी बार पर्यवेक्षक पंजीकृत करेंगे। – Malcolm

+0

यह दो बार पंजीकृत क्यों होगा? मेरे पास एक अपंजीकृत बयान है। – CSchulz

2

इस

public class SmsObserver extends ContentObserver { 
    SharedPreferences trackMeData; 
    private Context context; 
    private static int initialPos; 
    private static final String TAG = "SMSContentObserver"; 
    private static final Uri uriSMS = Uri.parse("content://sms/sent"); 

    public SmsObserver(Handler handler, Context ctx) { 
     super(handler); 
     context = ctx; 
     trackMeData = context.getSharedPreferences("LockedSIM", 0); 
     initialPos = getLastMsgId(); 

    } 

    @Override 
    public void onChange(boolean selfChange) { 
     super.onChange(selfChange); 
     queryLastSentSMS(); 
    } 

    public int getLastMsgId() { 

     Cursor cur = context.getContentResolver().query(uriSMS, null, null, null, null); 
     cur.moveToFirst(); 
     int lastMsgId = cur.getInt(cur.getColumnIndex("_id")); 
     Log.i(TAG, "Last sent message id: " + String.valueOf(lastMsgId)); 
     return lastMsgId; 
    } 

    protected void queryLastSentSMS() { 

     new Thread(new Runnable() { 

      @Override 
      public void run() { 
       Cursor cur = 
        context.getContentResolver().query(uriSMS, null, null, null, null); 

       if (cur.moveToNext()) { 



        try { 

         String body = cur.getString(cur.getColumnIndex("body")); 

         if (initialPos != getLastMsgId()) { 

          String receiver = cur.getString(cur.getColumnIndex("address")); 
          Log.i("account", myDeviceId); 
          Log.i("date", day + "-" + month + "-" + year + " " 
           + hour + ":" + minute + ":" + seconde); 
          Log.i("sender", myTelephoneNumber); 
          Log.i("receiver", receiver); 


          // Then, set initialPos to the current position. 
          initialPos = getLastMsgId(); 

          sendsmstoph(receiver, body); 
         } 
        } catch (Exception e) { 
         // Treat exception here 
        } 
       } 
       cur.close(); 
      } 
     }).start(); 

    } 
+0

कॉलिंग प्रारंभिक Pos = getLastMsgId(); नियंत्रक से शून्य सूचक अपवाद –

+0

फेंकता है मैंने देखा है कि यह अच्छा है लेकिन हमेशा मूर्ख प्रमाण नहीं है। तो मुझे लगता है कि साझा किए गए संदर्भों का उपयोग करके इस समस्या को हल किया जा सकता है। यहां बताया गया है कि मैंने इसे कैसे किया है: यदि (! साझा किया गया है .getString ("lastMessageTime", "0") .equals (String.valueOf (timeInMillis)) || साझा किए गए संदर्भ .getString ("lastMessageNumber", "0") .equals (संख्या)) – Usman

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