Android:使用 ContentObserver 或接收器无法捕获外发短信
Android : Catching Outgoing SMS using ContentObserver or receiver not working
我正在尝试使用内容观察器捕捉传出的 SMS 事件。
//TEST OBSERVER
ContentObserver co = new SMSoutObserver(new Handler(), getApplicationContext());
ContentResolver contentResolver = getApplicationContext().getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms/out"),true, co);
// END TEST OBSERVER
和
public class SMSoutObserver extends ContentObserver {
private Context mCtx;
public SMSoutObserver(Handler handler, Context ctx) {
super(handler);
mCtx = ctx;
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
// save the message to the SD card here
Logger.d("On Change");
Toast.makeText(mCtx,"TEST", Toast.LENGTH_LONG).show();
}
}
但是如果我在模拟器事件中发送传出消息,则不会触发。
我也试过使用接收器。
<receiver android:name=".receiver.SMSReceiver"
android:enabled="true"
android:exported="true"
android:priority="1000">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="android.provider.Telephony.SMS_SENT"/>
</intent-filter>
</receiver>
带接收器
public class SMSReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
Logger.d("SMSReceiver triggered");
if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
//do something with the received sms
Logger.d("Incoming SMS");
}else if(intent.getAction().equals("android.provider.Telephony.SMS_SENT")){
//do something with the sended sms
Logger.d("Outgoing SMS");
}
// Start reminder service
// context.startService(new Intent(context, ReminderService.class));
} catch (Exception e) {
Logger.e("onReceive method cannot be processed");
TrackingEventLogHelper.logException(e, Constants.Global.EXCEPTION,
Constants.ExceptionMessage.EXC_CANNOT_CANNOT_PROCESS_REBOOT_RECEIVER, true);
}
}
}
但此接收器仅针对传入消息触发,不会针对传出消息触发。我也应该如何以正确的方式处理 android 版本 > 5。
非常感谢任何建议
SDK 中没有 "android.provider.Telephony.SMS_SENT"
操作,也没有任何 system-wide 发送短信时的广播,所以您的第二种方法不会起作用。
至于ContentObserver
,您注册的Uri
必须是SMS Provider的基础Uri
。即,将Uri.parse("content://sms/out")
改为Uri.parse("content://sms")
。如果只想处理传出消息,则必须在 onChange()
方法中查询 Provider,并检索消息的 type
列值,检查 2
的值,表示已发送消息。
如果您支持低于 16 的 API 级别,那么它将是这样的:
private static final Uri uri = Uri.parse("content://sms");
private static final String COLUMN_TYPE = "type";
private static final int MESSAGE_TYPE_SENT = 2;
...
@Override
public void onChange(boolean selfChange) {
Cursor cursor = null;
try {
cursor = resolver.query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int type = cursor.getInt(cursor.getColumnIndex(COLUMN_TYPE));
if (type == MESSAGE_TYPE_SENT) {
// Sent message
}
}
}
finally {
if (cursor != null)
cursor.close();
}
}
从 API 16 开始,ContentObserver
class 提供了一个 onChange()
重载,它将为消息提供特定的 Uri
作为第二个参数,您可以比基础 Uri
更有效地查询和检查。此外,如果您的最低 API 级别是 19,则有几个 class 带有常量的元素可以替换上面示例代码中定义的那些。
附带说明一下,发件箱的 Uri
是 "content://sms/outbox"
,而不是 "content://sms/out"
。
我正在尝试使用内容观察器捕捉传出的 SMS 事件。
//TEST OBSERVER
ContentObserver co = new SMSoutObserver(new Handler(), getApplicationContext());
ContentResolver contentResolver = getApplicationContext().getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms/out"),true, co);
// END TEST OBSERVER
和
public class SMSoutObserver extends ContentObserver {
private Context mCtx;
public SMSoutObserver(Handler handler, Context ctx) {
super(handler);
mCtx = ctx;
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
// save the message to the SD card here
Logger.d("On Change");
Toast.makeText(mCtx,"TEST", Toast.LENGTH_LONG).show();
}
}
但是如果我在模拟器事件中发送传出消息,则不会触发。
我也试过使用接收器。
<receiver android:name=".receiver.SMSReceiver"
android:enabled="true"
android:exported="true"
android:priority="1000">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="android.provider.Telephony.SMS_SENT"/>
</intent-filter>
</receiver>
带接收器
public class SMSReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
Logger.d("SMSReceiver triggered");
if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
//do something with the received sms
Logger.d("Incoming SMS");
}else if(intent.getAction().equals("android.provider.Telephony.SMS_SENT")){
//do something with the sended sms
Logger.d("Outgoing SMS");
}
// Start reminder service
// context.startService(new Intent(context, ReminderService.class));
} catch (Exception e) {
Logger.e("onReceive method cannot be processed");
TrackingEventLogHelper.logException(e, Constants.Global.EXCEPTION,
Constants.ExceptionMessage.EXC_CANNOT_CANNOT_PROCESS_REBOOT_RECEIVER, true);
}
}
}
但此接收器仅针对传入消息触发,不会针对传出消息触发。我也应该如何以正确的方式处理 android 版本 > 5。
非常感谢任何建议
SDK 中没有 "android.provider.Telephony.SMS_SENT"
操作,也没有任何 system-wide 发送短信时的广播,所以您的第二种方法不会起作用。
至于ContentObserver
,您注册的Uri
必须是SMS Provider的基础Uri
。即,将Uri.parse("content://sms/out")
改为Uri.parse("content://sms")
。如果只想处理传出消息,则必须在 onChange()
方法中查询 Provider,并检索消息的 type
列值,检查 2
的值,表示已发送消息。
如果您支持低于 16 的 API 级别,那么它将是这样的:
private static final Uri uri = Uri.parse("content://sms");
private static final String COLUMN_TYPE = "type";
private static final int MESSAGE_TYPE_SENT = 2;
...
@Override
public void onChange(boolean selfChange) {
Cursor cursor = null;
try {
cursor = resolver.query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int type = cursor.getInt(cursor.getColumnIndex(COLUMN_TYPE));
if (type == MESSAGE_TYPE_SENT) {
// Sent message
}
}
}
finally {
if (cursor != null)
cursor.close();
}
}
从 API 16 开始,ContentObserver
class 提供了一个 onChange()
重载,它将为消息提供特定的 Uri
作为第二个参数,您可以比基础 Uri
更有效地查询和检查。此外,如果您的最低 API 级别是 19,则有几个 class 带有常量的元素可以替换上面示例代码中定义的那些。
附带说明一下,发件箱的 Uri
是 "content://sms/outbox"
,而不是 "content://sms/out"
。