在下面的示例中,我们使用一个
ContentObserver
来监视短信提供程序的更新。在触发SMS Intent之前创建并启动此Observer,并根据目标地址检查Provider更改。创建Observer的Activity必须实现
SmsSendObserver.SmsSendListener
接口以接收回调。
Observer的构造函数包括一个
timeout
参数(以毫秒为单位),以允许如果在合理的时间内未发送消息,则正确取消注册Observer。如果需要,可以将其设置为
NO_TIMEOUT
。但是,按照编写的方式,该类适用于“一次性”使用,它将在回调时取消注册自身并使成员为空。如果没有回调,可以使用
stop()
方法进行清理。在任一情况下,该实例不再可用,对它的任何引用都应设置为null。
示例Activity:
public class MainActivity extends Activity
implements SmsSendObserver.SmsSendListener {
...
private void sendMessage(String phoneNumber, String messageBody) {
new SmsSendObserver(this, phoneNumber, 15000).start();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("smsto:" + phoneNumber));
intent.putExtra("address", phoneNumber);
intent.putExtra("sms_body", messageBody);
intent.putExtra("exit_on_sent", true);
startActivity(intent);
}
public void onSmsSendEvent(boolean sent) {
Toast.makeText(this, sent ? "Message was sent" : "Timed out",
Toast.LENGTH_SHORT).show();
}
}
SmsSendObserver
类:
public class SmsSendObserver extends ContentObserver {
public static final int NO_TIMEOUT = -1;
private static final Handler handler = new Handler();
private static final Uri uri = Uri.parse("content://sms/");
private static final String COLUMN_ADDRESS = "address";
private static final String COLUMN_TYPE = "type";
private static final String[] PROJECTION = { COLUMN_ADDRESS, COLUMN_TYPE };
private static final int MESSAGE_TYPE_SENT = 2;
private Context context = null;
private ContentResolver resolver = null;
private String phoneNumber = null;
private long timeout = NO_TIMEOUT;
private boolean wasSent = false;
private boolean timedOut = false;
public SmsSendObserver(Context context, String phoneNumber, long timeout) {
super(handler);
if (context instanceof SmsSendListener) {
this.context = context;
this.resolver = context.getContentResolver();
this.phoneNumber = phoneNumber;
this.timeout = timeout;
}
else {
throw new IllegalArgumentException(
"Context must implement SmsSendListener interface");
}
}
private Runnable runOut = new Runnable() {
@Override
public void run() {
if (!wasSent) {
timedOut = true;
callBack();
}
}
};
public void start() {
if (resolver != null) {
resolver.registerContentObserver(uri, true, this);
if (timeout > NO_TIMEOUT) {
handler.postDelayed(runOut, timeout);
}
}
else {
throw new IllegalStateException(
"Current SmsSendObserver instance is invalid");
}
}
public void stop() {
if (resolver != null) {
resolver.unregisterContentObserver(this);
resolver = null;
context = null;
}
}
private void callBack() {
((SmsSendListener) context).onSmsSendEvent(wasSent);
stop();
}
@Override
public void onChange(boolean selfChange) {
if (wasSent || timedOut)
return;
Cursor cursor = null;
try {
cursor = resolver.query(uri, PROJECTION, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
final String address =
cursor.getString(cursor.getColumnIndex(COLUMN_ADDRESS));
final int type =
cursor.getInt(cursor.getColumnIndex(COLUMN_TYPE));
if (PhoneNumberUtils.compare(address, phoneNumber) &&
type == MESSAGE_TYPE_SENT) {
wasSent = true;
callBack();
}
}
}
finally {
if (cursor != null) {
cursor.close();
}
}
}
public interface SmsSendListener {
public void onSmsSendEvent(boolean sent);
}
}