2012-02-02 7 views
6

Я знаю, что этот вопрос задан несколько раз, но никто не смог найти рабочий ответ от того, что я видел.Sms ContentObserver onChange() срабатывает несколько раз

Im, работая над приложением для перехвата текстовых сообщений и в зависимости от отправки #, появляется с настраиваемым предупреждением. Я прекрасно работаю с широковещательным приемником, однако, если пользователь установил goSms, метод onReceive() никогда не вызывается, поскольку goSms прерывает его, прежде чем он когда-либо достигнет моего приложения.

Чтобы обойти это, я пытаюсь использовать наблюдателя контента на content://sms/ Его работа просто прекрасна, однако onChange() вызывается дважды, с точно такими же параметрами. Ive пытался проверить метки времени, но они такие же, как и тип и каждый другой параметр, который я установил.

Из того, что я видел, это распространенная проблема, но не та, которую я видел нигде.

@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() увольнения дважды, Im получение двух предупреждений, а также. Я не могу, чтобы жизнь меня определяла путь вокруг этого.

+1

Ссылки на другие (неполные) ответы были бы полезны – KevinDTimm

ответ

4

Если две одинаковые:
магазин каждое сообщение recv'd
сравнить его с предыдущими сообщениями recv'd
если не найден, процесс
если он найден, удалить сообщение

Житие сохраненные сообщения должны быть бесконечно малыми, маленький круговой буфер из 5 сообщений должен быть точным.

+0

сообщение только получено один раз. его не приходилось дважды. tbh, я даже не знаю, из чего запускается второй 'onChange'. – r2DoesInc

+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

3

Вы можете сохранить идентификатор последнего сообщения и сравнить его с идентификатором сообщения, которое возвращается cur в onChange. вы можете просто игнорировать сообщение, если идентификаторы одинаковы.

// 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 SMS только предотвращает другие приложения от ПОЛУЧАТЬ Broadcast, если пользователь выбрал этот вариант (ПРИИЕ Настройки - Отключить другие уведомления о сообщении) - так что если пользователь не хочет, чтобы другие приложения, чтобы мешать ему - я подумайте, что это хорошая идея не делать этого.

+0

Приложение, в котором я работаю, не является тем, которое следует игнорировать, когда-либо. Его необходимо предустановить на устройствах и добиться полного приоритета над тем, что в настоящее время работает на телефоне. Я сделал что-то похожее на это, если вы посмотрите в комментариях нижеприведенного ответа. – r2DoesInc

+1

вы понимаете, что фрагмент, который вы опубликовали, должен идти действительно, очень долгий путь, прежде чем его можно будет использовать в приложении, которое должно быть запрограммировано, не так ли? – Vladimir

+0

о да конечно. ive только начал проект. его пройти долгий путь – r2DoesInc

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.

Смежные вопросы