检测由于内容长度而发送的多条SMS

时间:2016-12-19 10:58:54

标签: android sms contentobserver

我已为registerContentObserver设置后台服务,以便在发送短信时收到通知。收到此事件后,我会增加一个变量以了解发送的消息数。这是按预期工作的。

当有人发送超过140个字符的短信时,移动运营商会将此视为多条短信,但似乎我只收到1条已发送短信的回调。这导致我的应用程序错过了对某些消息的计数。

有没有正确的方法知道实际发送了多少邮件?

1 个答案:

答案 0 :(得分:1)

当应用负责将自己的消息写入提供者时,无论消息是否必须作为多部分发送,它最有可能一次写入整个消息。这就是为什么你的Observer经常只为每个完整的消息发射一次,无论多大。

由于KitKat,系统会自动保存任何非默认应用程序的外发消息,对于多部分消息,每个部分都将单独保存,每次都会触发Observer。当然,这对KitKat之前的任何事情都没有帮助,或者默认应用程序在以后的版本中保存自己的消息。

一种可能性是在ContentObserver中获取邮件正文,并确定它将被拆分的邮件部分的数量。 SmsMessage.calculateLength()方法可以为我们执行此操作。它返回一个int数组,其第一个元素将包含给定文本的消息计数。

例如,使用旧的onChange(boolean)方法来支持API< 16:

private class SmsObserver extends ContentObserver {
    private static final Uri SMS_SENT_URI = Uri.parse("content://sms/sent");
    private static final String COLUMN_ID = "_id";
    private static final String COLUMN_BODY = "body";
    private static final String[] PROJECTION = {COLUMN_ID, COLUMN_BODY};

    // You might want to persist this value to storage, rather than
    // keeping a field, in case the Observer is killed and recreated.
    private int lastId;

    public SmsObserver(Handler handler) {
        super(handler);
    }

    @Override
    public void onChange(boolean selfChange) {
        Cursor c = null;
        try {
            // Get the most recent sent message.
            c = getContentResolver().query(SMS_SENT_URI, PROJECTION, null,
                                           null, "date DESC LIMIT 1");
            if (c != null && c.moveToFirst()) {

                // Check that we've not already counted this one.
                final int id = c.getInt(c.getColumnIndex(COLUMN_ID));
                if (id == lastId) {
                    return;
                }
                lastId = id;

                // Get the message body, and have the SmsMessage
                // class calculate how many parts it would need.
                final String body = c.getString(c.getColumnIndex(COLUMN_BODY));
                final int numParts = SmsMessage.calculateLength(body, false)[0];

                // Add the number of parts to the count,
                // however you might be doing that.
                addToCount(numParts);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            if (c != null) {
                c.close();
            }
        }
    }
}

如果您支持API 16及更高版本,我们可以使用onChange(boolean, Uri)重载,事情变得更简单,因为我们不一定需要跟踪最后的消息ID。

@Override
public void onChange(boolean selfChange, Uri uri) {
    Cursor c = null;
    try {
        // type=2 restricts the query to the sent box, so this just
        // won't return any records if the Uri isn't for a sent message.
        c = getContentResolver().query(uri, PROJECTION, "type=2", null, null);
        if (c != null && c.moveToFirst()) {
            final String body = c.getString(c.getColumnIndex(COLUMN_BODY));
            final int numParts = SmsMessage.calculateLength(body, false)[0];

            addToCount(numParts);
        }
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        if (c != null) {
            c.close();
        }
    }
}
相关问题