2012-02-02 113 views
6

我知道這個問題已被多次詢問,但沒有人能夠拿出我所見過的工作答案。短信ContentObserver onChange()多次觸發

我正在一個應用程序攔截文本消息,並根據發送#,彈出一個自定義提醒。我用廣播接收機工作得很漂亮,但是如果用戶安裝了goSms,onReceive()方法永遠不會被調用,因爲goSms會在它到達我的應用程序之前中止它。

爲了解決這個問題,我試着在content://sms/ 其內容觀測工作得很好,但是onChange()被調用兩次,具有完全相同的參數。我試圖檢查時間戳,但是它們是一樣的,就像我設置的類型和每個其他參數一樣。

從我所看到的情況來看,這是一個常見問題,但不是我見過的任何地方都能找到答案的問題。

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

protected void querySMS() { 
    Cursor cur = getContentResolver().query(u, null, null, null, null); 
    cur.moveToNext(); // this will make it point to the first record, which is the last SMS sent 
    String type = cur.getString(cur.getColumnIndex("type")); 
    String body = cur.getString(cur.getColumnIndex("body")); //content of sms 
    String add = cur.getString(cur.getColumnIndex("address")); //phone num 
    if (type.equals("1")) { 
     if (add.equals(Test.SENDER)) {    
      String[] bodys = body.split(" ", 7); 
      if (bodys[0].equals("test")) { 
       test = true; 
      } 
      cat = bodys[1]; 
      level = bodys[2]; 
      urgency = bodys[3]; 
      certainty = bodys[4]; 
      carrier = bodys[5]; 
      message = bodys[6]; 
      final Intent intent = new Intent(context, AlertActivity.class); 
      Bundle b = new Bundle(); 
      b.putString("title", cat); 
      b.putString("certainty", certainty); 
      b.putString("urgency", urgency); 
      b.putString("level", level); 
      b.putString("message", message); 
      b.putBoolean("test", test); 
      intent.putExtras(b); 
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
      intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
      TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 
      carrierName = manager.getNetworkOperatorName(); 
      if (carrierName.replaceAll(" ", "").equals(carrier)) { 

       context.startActivity(intent); 
      } else { 
       //testing 
       Toast.makeText(context, carrierName.replaceAll(" ", ""), Toast.LENGTH_LONG).show(); 
      } 
     } 
    } 
} 

由於onChange()被激發兩次,我也得到兩個警報。我不能爲了我的生活找出解決辦法。

+1

鏈接到其他(不完整)的答案將是有幫助的 – KevinDTimm 2012-02-02 19:19:29

回答

4

如果兩個是相同的:
存儲每個消息recv'd
比較它以前的消息recv'd
如果沒有找到,處理
如果找到,則丟棄該消息

的壽命存儲的消息應該是無限小的,5個消息的循環緩衝區應該沒問題。

+0

該消息只被接收一次,但。它不會進來兩次。 tbh,我什至不知道第二個'onChange'甚至被觸發。 – r2DoesInc 2012-02-02 19:27:04

+2

啊。加上你的想法與http://stackoverflow.com/questions/7012703/android-detect-sms-outgoing-incorrect-count,我得到它的工作。我想我第一次讀到它時誤解了你的意思。我創建了一個靜態'arrayList'並用它來檢查。 \t \t \t'if(!ids.contains(id)){ids.add(id); context.startActivity(intent);}' – r2DoesInc 2012-02-02 19:34:14

3

您可以保存最後一條消息的ID並將其與curonChange返回的消息的ID進行比較。如果id相同,你可以簡單地忽略該消息。

// might contain mistakes, but you'll get the idea: 
protected void querySMS() { 
    Cursor cur = getContentResolver().query(u, null, null, null, null); 
    cur.moveToNext(); 
    if (lastId == cur.getLong(cur.getColumnIndex("_id"))) 
     return; 
    lastId = cur.getLong(cur.getColumnIndex("_id")); 
    ... //continue as it was 
} 

但是 - GO短信只是阻止其他應用程序的距離,如果用戶選擇了該選項recieving廣播(收到設置 - 禁用其他消息通知) - 所以,如果用戶不希望其他應用程序去打擾他 - 我認爲不這樣做是個好主意。

+0

我的工作應用程序不應該被忽略,永遠。它預裝在設備上,並且優先於當前在手機上運行的其他任何內容。我做了類似的事情,如果你看下面的答案的評論,你可以看到。 – r2DoesInc 2012-02-02 19:37:09

+1

你確實明白,你發佈的代碼片段在應用程序可以用於預先安裝之前應該真的非常長,不是嗎? – Vladimir 2012-02-02 19:43:30

+0

當然哦,是的。我只是剛剛開始這個項目。它還有很長的路要走 – r2DoesInc 2012-02-02 19:47:19

4

這裏是我的代碼,它工作正常,我

public class SmsObserver extends ContentObserver { 
    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; 
     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 { 
         if (initialPos != getLastMsgId()) { 
          // Here you get the last sms. Do what you want. 
          String receiver = cur.getString(cur.getColumnIndex("address")); 
          System.out.println(" Receiver Ph no :"+receiver); 


          // Then, set initialPos to the current position. 
          initialPos = getLastMsgId(); 
         } 
        } catch (Exception e) { 
         // Treat exception here 
        } 
       } 
       cur.close(); 
      } 
     }).start(); 

    } 

}//End of class SmsObserver 
0

我只是用SharedPreference此言最後SMS信息(如:id\type ...)。如果是相同的,我會return

相關問題