短信-彩信 Class 意外结果
SMS-MMS Class Unexpected Results
我在使用此 sms-mms class 时遇到了一些问题,问题是 returns 是预期数据的 6 倍。它显示之前的 3 条消息,然后显示 3 条当前的消息,我只需要 1 条当前的消息,但不确定如何以 6 结束...像这样;
V/Debug: 观察者开始
V/Debug: 收到短信
V/Debug:发件人:+15555551212
V/Debug:类型:1
V/Debug:时间:2 月 9 日星期五 10:01:53 2018 年美国东部时间
V/Debug:正文:一些短信...
重建Class来源
public class MessageService extends Service {
private static final String VER = "1.1.10";
private static final String TAG = "ClassMessageService";
private ContentResolver contentResolver;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
Log.v(TAG, "Message capturing service version: " + VER);
Log.v(TAG, "Message capturing service created " + ReturnCurrentDateTime());
}
public int onStartCommand(Intent intent, int flags, int startId) {
registerObserver();
return START_STICKY;
}
public void registerObserver() {
contentResolver = getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://mms-sms"), true, new MessageObserver(new Handler()));
}
public String ReturnCurrentDateTime() {
Date datetime = new Date();
datetime.getTime();
return datetime.toString();
}
class MessageObserver extends ContentObserver {
private final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int SMS_MESSAGE = 0;
private static final int MMS_MESSAGE = 1;
//static {
// MATCHER.addURI("sms", "#", SMS_MESSAGE);
// MATCHER.addURI("mms", "#", MMS_MESSAGE);
//}
public MessageObserver(Handler handler) {
super(handler);
Log.v(TAG, "MessageObserver...");
MATCHER.addURI("sms", "#", SMS_MESSAGE);
MATCHER.addURI("mms", "#", MMS_MESSAGE);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
switch (MATCHER.match(uri)) {
case SMS_MESSAGE:
Cursor cursor = contentResolver.query(uri, null, null, null, null);
cursor.moveToNext();
String msg_id;
String phone;
String dateVal;
String body;
Date date;
msg_id = cursor.getString(cursor.getColumnIndex("_id"));
phone = cursor.getString(cursor.getColumnIndex("address"));
dateVal = cursor.getString(cursor.getColumnIndex("date"));
body = cursor.getString(cursor.getColumnIndex("body"));
date = new Date(Long.valueOf(dateVal));
Log.v(TAG, "SMS: " + phone + " " + body + " " + msg_id + " " + date);
break;
case MMS_MESSAGE:
Cursor mcursor = contentResolver.query(uri, null, null, null, null);
mcursor.moveToNext();
String mmsg_id;
String mphone;
String mdateVal;
String mbody;
Date mdate;
mmsg_id = mcursor.getString(mcursor.getColumnIndex("_id"));
mphone = mcursor.getString(mcursor.getColumnIndex("address"));
mdateVal = mcursor.getString(mcursor.getColumnIndex("date"));
mbody = mcursor.getString(mcursor.getColumnIndex("body"));
mdate = new Date(Long.valueOf(mdateVal));
Log.v(TAG, "SMS: " + mphone + " " + mbody + " " + mmsg_id + " " + mdate);
break;
default:
}
}
}
}
在 content://mms-sms
URI 上注册您的 ContentObserver
– 大概是 true
用于后代 – 通常会给您带来很多冗余和不相关的更改通知,并且您的观察者正在响应所有这些。
标准 SmsProvider
和 MmsProvider
都会向多个 URI 发送更改通知。例如,标准 SmsProvider
调度到特定的 content://sms/#
URI(其中 #
是消息 ID),以及一般的 content://mms-sms
URI,content://mms-sms/conversation
网址。您的观察者正在处理的每条消息至少有两个通知。
此外,MmsSmsProvider
——一般处理线程(对话),而不是单独的消息——可以在修改线程时在 content://mms-sms
上触发更改通知;例如,更新其摘要,将其标记为已读等。如果您真的只想跟踪消息发送或接收,这些更改是无关紧要的,但您的 Observer 每次仍在抓取和处理最新消息。
我推荐的解决方案分为两部分:更改您的 ContentObserver
以覆盖 onChange(boolean, Uri)
方法,并分别在 content://sms
和 content://mms
URI 上注册.
首先,ContentObserver
自 API 级别 16 以来有一个带有 Uri
参数的 onChange()
方法。即:
@Override
public void onChange(boolean selfChange, Uri uri) {
...
}
独自一人,对您的观察者的这种更改不会有太大帮助,因为您到达那里的 Uri
可能是通用 URI – 例如,content://mms-sms
或 content://mms-sms/conversation
–没有其他身份信息。
第二个建议解决了这个问题——分别在 content://sms
和 content://mms
上注册,而不是在 content://mms-sms
上注册。即:
getContentResolver().registerContentObserver(Uri.parse("content://sms"), ...);
getContentResolver().registerContentObserver(Uri.parse("content://mms"), ...);
这样做会阻止您的观察者在 content://mms-sms
URI 上收到不相关的通知,并且您应该在 onChange()
中获得更具体的 Uri
,形式为 content://sms/#
或 content://mms/#
,其中 #
是消息的 ID,long
。此 Uri
可用于检查消息是 SMS 还是 MMS,以及它是否是您感兴趣的更改,作为不相关更改的 URI——例如,对 SMS 的更改 raw
table – 不应匹配这些表格。
如果对两个已注册的 Uri
使用单个 Observer*,则可以使用 UriMatcher
.例如:
public class MessageObserver extends ContentObserver {
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int SMS_MESSAGE = 0;
private static final int MMS_MESSAGE = 1;
static {
MATCHER.addURI("sms", "#", SMS_MESSAGE);
MATCHER.addURI("mms", "#", MMS_MESSAGE);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
switch (MATCHER.match(uri)) {
case SMS_MESSAGE:
break;
case MMS_MESSAGE:
break;
default:
}
}
...
}
此外,您可以直接使用特定的 Uri
查询来获取单个消息的详细信息,而不是查询一般的 content://sms
和 content://mms
URI,然后获取每个任一提供者中的消息,仅检查第一个。
最后,您可能已经注意到我在这里限定了许多语句,如 "should"、"likely" 等。这些提供程序的实现可能与预期的。我建议您尽可能彻底地测试您的 Observer。
* 据我所知,为多个 URI 注册单个 Observer 实例没有问题,我的测试也从未出现过任何问题。但是,您当然可以为 SMS 和 MMS 实现单独的 ContentObserver
,并且 UriMatcher
仍然可以用于过滤不相关的 URI。
我在使用此 sms-mms class 时遇到了一些问题,问题是 returns 是预期数据的 6 倍。它显示之前的 3 条消息,然后显示 3 条当前的消息,我只需要 1 条当前的消息,但不确定如何以 6 结束...像这样;
V/Debug: 观察者开始
V/Debug: 收到短信
V/Debug:发件人:+15555551212
V/Debug:类型:1
V/Debug:时间:2 月 9 日星期五 10:01:53 2018 年美国东部时间
V/Debug:正文:一些短信...
重建Class来源
public class MessageService extends Service {
private static final String VER = "1.1.10";
private static final String TAG = "ClassMessageService";
private ContentResolver contentResolver;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
Log.v(TAG, "Message capturing service version: " + VER);
Log.v(TAG, "Message capturing service created " + ReturnCurrentDateTime());
}
public int onStartCommand(Intent intent, int flags, int startId) {
registerObserver();
return START_STICKY;
}
public void registerObserver() {
contentResolver = getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://mms-sms"), true, new MessageObserver(new Handler()));
}
public String ReturnCurrentDateTime() {
Date datetime = new Date();
datetime.getTime();
return datetime.toString();
}
class MessageObserver extends ContentObserver {
private final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int SMS_MESSAGE = 0;
private static final int MMS_MESSAGE = 1;
//static {
// MATCHER.addURI("sms", "#", SMS_MESSAGE);
// MATCHER.addURI("mms", "#", MMS_MESSAGE);
//}
public MessageObserver(Handler handler) {
super(handler);
Log.v(TAG, "MessageObserver...");
MATCHER.addURI("sms", "#", SMS_MESSAGE);
MATCHER.addURI("mms", "#", MMS_MESSAGE);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
switch (MATCHER.match(uri)) {
case SMS_MESSAGE:
Cursor cursor = contentResolver.query(uri, null, null, null, null);
cursor.moveToNext();
String msg_id;
String phone;
String dateVal;
String body;
Date date;
msg_id = cursor.getString(cursor.getColumnIndex("_id"));
phone = cursor.getString(cursor.getColumnIndex("address"));
dateVal = cursor.getString(cursor.getColumnIndex("date"));
body = cursor.getString(cursor.getColumnIndex("body"));
date = new Date(Long.valueOf(dateVal));
Log.v(TAG, "SMS: " + phone + " " + body + " " + msg_id + " " + date);
break;
case MMS_MESSAGE:
Cursor mcursor = contentResolver.query(uri, null, null, null, null);
mcursor.moveToNext();
String mmsg_id;
String mphone;
String mdateVal;
String mbody;
Date mdate;
mmsg_id = mcursor.getString(mcursor.getColumnIndex("_id"));
mphone = mcursor.getString(mcursor.getColumnIndex("address"));
mdateVal = mcursor.getString(mcursor.getColumnIndex("date"));
mbody = mcursor.getString(mcursor.getColumnIndex("body"));
mdate = new Date(Long.valueOf(mdateVal));
Log.v(TAG, "SMS: " + mphone + " " + mbody + " " + mmsg_id + " " + mdate);
break;
default:
}
}
}
}
在 content://mms-sms
URI 上注册您的 ContentObserver
– 大概是 true
用于后代 – 通常会给您带来很多冗余和不相关的更改通知,并且您的观察者正在响应所有这些。
标准 SmsProvider
和 MmsProvider
都会向多个 URI 发送更改通知。例如,标准 SmsProvider
调度到特定的 content://sms/#
URI(其中 #
是消息 ID),以及一般的 content://mms-sms
URI,content://mms-sms/conversation
网址。您的观察者正在处理的每条消息至少有两个通知。
此外,MmsSmsProvider
——一般处理线程(对话),而不是单独的消息——可以在修改线程时在 content://mms-sms
上触发更改通知;例如,更新其摘要,将其标记为已读等。如果您真的只想跟踪消息发送或接收,这些更改是无关紧要的,但您的 Observer 每次仍在抓取和处理最新消息。
我推荐的解决方案分为两部分:更改您的 ContentObserver
以覆盖 onChange(boolean, Uri)
方法,并分别在 content://sms
和 content://mms
URI 上注册.
首先,ContentObserver
自 API 级别 16 以来有一个带有 Uri
参数的 onChange()
方法。即:
@Override
public void onChange(boolean selfChange, Uri uri) {
...
}
独自一人,对您的观察者的这种更改不会有太大帮助,因为您到达那里的 Uri
可能是通用 URI – 例如,content://mms-sms
或 content://mms-sms/conversation
–没有其他身份信息。
第二个建议解决了这个问题——分别在 content://sms
和 content://mms
上注册,而不是在 content://mms-sms
上注册。即:
getContentResolver().registerContentObserver(Uri.parse("content://sms"), ...);
getContentResolver().registerContentObserver(Uri.parse("content://mms"), ...);
这样做会阻止您的观察者在 content://mms-sms
URI 上收到不相关的通知,并且您应该在 onChange()
中获得更具体的 Uri
,形式为 content://sms/#
或 content://mms/#
,其中 #
是消息的 ID,long
。此 Uri
可用于检查消息是 SMS 还是 MMS,以及它是否是您感兴趣的更改,作为不相关更改的 URI——例如,对 SMS 的更改 raw
table – 不应匹配这些表格。
如果对两个已注册的 Uri
使用单个 Observer*,则可以使用 UriMatcher
.例如:
public class MessageObserver extends ContentObserver {
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int SMS_MESSAGE = 0;
private static final int MMS_MESSAGE = 1;
static {
MATCHER.addURI("sms", "#", SMS_MESSAGE);
MATCHER.addURI("mms", "#", MMS_MESSAGE);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
switch (MATCHER.match(uri)) {
case SMS_MESSAGE:
break;
case MMS_MESSAGE:
break;
default:
}
}
...
}
此外,您可以直接使用特定的 Uri
查询来获取单个消息的详细信息,而不是查询一般的 content://sms
和 content://mms
URI,然后获取每个任一提供者中的消息,仅检查第一个。
最后,您可能已经注意到我在这里限定了许多语句,如 "should"、"likely" 等。这些提供程序的实现可能与预期的。我建议您尽可能彻底地测试您的 Observer。
* 据我所知,为多个 URI 注册单个 Observer 实例没有问题,我的测试也从未出现过任何问题。但是,您当然可以为 SMS 和 MMS 实现单独的 ContentObserver
,并且 UriMatcher
仍然可以用于过滤不相关的 URI。