我已为registerContentObserver
设置后台服务,以便在发送短信时收到通知。收到此事件后,我会增加一个变量以了解发送的消息数。这是按预期工作的。
当有人发送超过140个字符的短信时,移动运营商会将此视为多条短信,但似乎我只收到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();
}
}
}