2012-02-02 177 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

相关问题