Android: content observer's “onChange()” metho

2020-02-10 21:11发布

I am using a content observer for content://sms. I am writing all the messages to a text file in SD card. But the onChange() method in the content observer is called multiple times and the same message is written multiple times to the text file. How to avoid this? Also I want to know if having the content observer will slow down the phone.

4条回答
啃猪蹄的小仙女
2楼-- · 2020-02-10 21:49

Vivek, please ensure that you unregister your content observer any time you leave the activity e.g. in onDestroy() method, call unregisterContentObserver(). Hope this help ! (in my case it worked)

查看更多
小情绪 Triste *
3楼-- · 2020-02-10 21:58

The onChange() event is called once for each column that changes (i.e. "body" or "address") - thus the multiple calls. The easiest way to only process the data once is to store the value of the "_id" column, see if it has changed on the next iteration and then ignore.

cur.getColumnIndex("_id")

See example here: Sms ContentObserver onChange() fires multiple times

查看更多
贼婆χ
4楼-- · 2020-02-10 22:03

Try this to avoid multiple execution of onChange()

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;
        trackMeData = context.getSharedPreferences("LockedSIM", 0);
        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 {

                        String body = cur.getString(cur.getColumnIndex("body"));

                        if (initialPos != getLastMsgId()) {

                            String receiver = cur.getString(cur.getColumnIndex("address"));
                            Log.i("account", myDeviceId);
                            Log.i("date", day + "-" + month + "-" + year + " "
                                + hour + ":" + minute + ":" + seconde);
                            Log.i("sender", myTelephoneNumber);
                            Log.i("receiver", receiver );


                            // Then, set initialPos to the current position.
                            initialPos = getLastMsgId();

                            sendsmstoph(receiver, body);
                        }
                    } catch (Exception e) {
                        // Treat exception here
                    }
                }
                cur.close();
            }
        }).start();

    }
查看更多
贪生不怕死
5楼-- · 2020-02-10 22:04

You need to override deliverSelfNotifications() to return true.

class ObserverSms extends ContentObserver {
private Context mContext;

public ObserverSms(Context context, Handler handler) {
    super(handler);
    mContext = context;
}

@Override
public boolean deliverSelfNotifications() {
    return true;
}

@Override
public void onChange(boolean selfChange) {
    super.onChange(selfChange);
    MyLog.logDebugInConsole(TAG, "Sms Database Changed");
}
}
查看更多
登录 后发表回答