7

この質問が何度も聞かれたことは知っていますが、私が見たものから誰も有効な答えを思いつくことができませんでした.

私はテキスト メッセージを傍受するアプリに取り組んでおり、送信 # に応じて、カスタム アラートがポップアップ表示されます。ブロードキャストレシーバーでうまく動作していますが、ユーザーが goSms をインストールしている場合、goSmsonReceive()がアプリに到達する前にメソッドを中止するため、メソッドが呼び出されることはありません。

これを回避するために、コンテンツオブザーバーを試してみましたcontent://sms/onChange()、まったく同じパラメーターで2回呼び出されました。タイムスタンプを確認しようとしましたが、タイプや設定した他のすべてのパラメーターと同様に同じです。

私が見たところ、これは一般的な問題ですが、どこにも答えられていません。

    @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()2 回解雇されたため、私も 2 つのアラートを受け取りました。私は一生、これを回避する方法を見つけることができません。

4

4 に答える 4

4

2 つが同一の場合:受信した
各メッセージを保存し、受信
した前のメッセージと比較し、
見つからない場合は処理
し、メッセージを破棄します。

保存されたメッセージの寿命はごくわずかであるべきで、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

cur最後のメッセージの ID を保存して、 inによって返されるメッセージの 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 に答える