Sms ContentObserver onChange () срабатывает несколько раз - PullRequest
7 голосов
/ 02 февраля 2012

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

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

Ответы [ 4 ]

4 голосов
/ 25 декабря 2013

вот мой код, у меня он отлично работает

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
4 голосов
/ 02 февраля 2012

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

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

3 голосов
/ 02 февраля 2012

Вы можете сохранить идентификатор последнего сообщения и сравнить его с идентификатором сообщения, которое возвращается 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 не позволяет другим приложениям получать широковещательную рассылку, только если пользователь выбрал эту опцию ( Получить настройки - Отключить уведомления о других сообщениях ) - поэтому, если пользователь не хочет, чтобы другие приложения мешали ему, думаю, что это хорошая идея - не делать этого.

0 голосов
/ 29 мая 2015

Я просто использую SharedPreference, чтобы отметить последнюю информацию SMS (например: id\type ...).если это то же самое, я буду return.

...