7

我知道这个问题已被多次问过,但没有人能够从我所看到的情况中得出一个可行的答案。

我正在开发一个应用程序来拦截短信,并根据发送#,弹出一个自定义警报。我让它与广播接收器一起工作得很好,但是如果用户安装了 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 回答 4

4

如果两者相同:
存储每条消息recv'd
将其与以前的消息recv'd进行比较,
如果没有找到,处理
如果找到,丢弃消息

存储的消息的寿命应该是无限小的,5 条消息的小循环缓冲区应该没问题。

于 2012-02-02T19:21:43.217 回答
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
于 2013-12-25T05:03:50.703 回答
3

您可以保存最后一条消息的 id 并将其与curin返回的消息的 id 进行比较onChange。然后,如果 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 SMS 只会阻止其他应用程序接收广播- 因此,如果用户不希望其他应用程序打扰他 - 我认为不这样做是个好主意。

于 2012-02-02T19:27:24.610 回答
0

我只是使用 SharedPreference 来备注最后的 SMS 信息(如:id\type...)。如果是一样的,我会的return

于 2015-05-29T03:45:14.563 回答