【发布时间】:2011-08-14 02:15:51
【问题描述】:
我正在开发一个应用程序,它将所有传入和传出的短信存储在 SD 卡中的文本文件中。
我可以使用广播接收器收听传入的消息。我发现很难收听传出的短信。
我在某种程度上知道需要设置已发送箱或发件箱上的内容观察器,但我不知道该怎么做。
如何做到这一点?
【问题讨论】:
我正在开发一个应用程序,它将所有传入和传出的短信存储在 SD 卡中的文本文件中。
我可以使用广播接收器收听传入的消息。我发现很难收听传出的短信。
我在某种程度上知道需要设置已发送箱或发件箱上的内容观察器,但我不知道该怎么做。
如何做到这一点?
【问题讨论】:
基本上,你必须注册一个内容观察者......像这样:
ContentResolver contentResolver = context.getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms/out"),true, yourObserver);
yourObserver 是一个可能如下所示的对象 (new YourObserver(new Handler())):
class YourObserver extends ContentObserver {
public YourObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
// save the message to the SD card here
}
}
那么,您究竟是如何获得短信内容的呢?你必须使用Cursor:
// save the message to the SD card here
Uri uriSMSURI = Uri.parse("content://sms/out");
Cursor cur = this.getContentResolver().query(uriSMSURI, null, null, null, null);
// this will make it point to the first record, which is the last SMS sent
cur.moveToNext();
String content = cur.getString(cur.getColumnIndex("body"));
// use cur.getColumnNames() to get a list of all available columns...
// each field that compounds a SMS is represented by a column (phone number, status, etc.)
// then just save all data you want to the SDcard :)
【讨论】:
这是我解决这个问题的方法
在其中创建一个内容观察者
@Override
public int onStartCommand(Intent intent, int flag, int startId) {
MyObserver myObserver = new MyObserver(new Handler());
ContentResolver contentResolver = this.getApplicationContext().getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms/sent"), true, myObserver);
return START_STICKY;
}
创建观察者类
class MyObserver extends ContentObserver {
public MyObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Uri uriSMSURI = Uri.parse("content://sms/sent");
Cursor cur = getContentResolver().query(uriSMSURI, null, null, null, null);
cur.moveToNext();
String content = cur.getString(cur.getColumnIndex("body"));
String smsNumber = cur.getString(cur.getColumnIndex("address"));
if (smsNumber == null || smsNumber.length() <= 0) {
smsNumber = "Unknown";
}
cur.close();
if(smsChecker( "OutgoingSMS to " + smsNumber + ": " + content)) {
//save data into database/sd card here
}
}
}
我添加了一个方法 smsChecker() 来检查新消息是否与上一条消息相同
public boolean smsChecker(String sms) {
boolean flagSMS = true;
if (sms.equals(lastSMS)) {
flagSMS = false;
}
else {
lastSMS = sms;
}
//if flagSMS = true, those 2 messages are different
return flagSMS;
}
如果我没记错的话,如果我们只想检查所有发送的消息,我们使用“content://sms/sent”,如果我们只想检查发件箱内的所有消息,我们使用“content://sms/out”,如果我们想检查所有消息,则为“content://sms”。
【讨论】:
这是我的版本,已在Android 6.0+中验证
class smsObserver extends ContentObserver {
private String lastSmsId;
public smsObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Uri uriSMSURI = Uri.parse("content://sms/sent");
Cursor cur = getContentResolver().query(uriSMSURI, null, null, null, null);
cur.moveToNext();
String id = cur.getString(cur.getColumnIndex("_id"));
if (smsChecker(id)) {
String address = cur.getString(cur.getColumnIndex("address"));
// Optional: Check for a specific sender
if (address.equals(phoneNumber)) {
String message = cur.getString(cur.getColumnIndex("body"));
// Use message content for desired functionality
}
}
}
// Prevent duplicate results without overlooking legitimate duplicates
public boolean smsChecker(String smsId) {
boolean flagSMS = true;
if (smsId.equals(lastSmsId)) {
flagSMS = false;
}
else {
lastSmsId = smsId;
}
return flagSMS;
}
}
将此代码放在应启用观察者的位置
ContentResolver contentResolver = getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms"), true, new smsObserver(new Handler()));
这假设您正在使用一个活动。请记住,您需要一个上下文引用才能从服务或接收器中调用getContentResolver()。
【讨论】:
mContext 是上下文引用。听起来您可能不熟悉上下文。我建议在 stackoverflow.com/a/14230055/461982 上查看有关如何获取上下文参考的答案。
我看到出了什么问题。上线了:
contentResolver.registerContentObserver(Uri.parse("content://sms/sent"), true, _myObserver);
您必须删除 '/sent' 并只写 'content://sms' 它已在 ContentObserver 中指定以查看发送的短信。
【讨论】: