android - 检测由于内容长度而发送的多条短信

标签 android sms contentobserver

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

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

有没有什么正确的方法可以知道实际发送了多少消息?

最佳答案

当应用程序负责将自己的消息写入 Provider 时,它很可能会一次写入整个消息,无论消息是否必须作为多部分发送。这就是为什么您的 Observer 通常只为每条完整的消息触发一次,无论消息有多大。

自 KitKat 起,系统将自动保存任何非默认应用程序的传出消息,而对于多部分消息,每个部分将单独保存,每次都会触发你的观察者。当然,这对 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();
        }
    }
}

关于android - 检测由于内容长度而发送的多条短信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41221109/

相关文章:

java - 使用 SIM2 发送消息

android - 如何给评级栏星之间的间距 android?

android - 如何处理 editText 中 imageSpan 的 onClick 事件?

android - 显示用于在Android中向我的手机发送短信的SMSC地址

android - 如何始终收听短信android

android - 在 list 文件中使用 contentObserver

android - 在 Android 内容观察器中观察 Audio.Media.EXTERNAL_CONTENT_URI 的变化

android - 在服务中实现广播接收器

android - 如何与此应用程序中的 facebook 和 twitter 按钮共享 android 应用程序