我知道这个问题已被多次询问,但没有人能够从我所看到的那里得到一个有效的答案。
我正在使用应用拦截短信,并根据发送信息#弹出自定义提醒。我使用广播接收器可以很好地工作,但是如果用户安装了goSms,则永远不会调用onReceive()
方法,因为goSms在到达我的应用之前就会中止它。
为了解决这个问题,我在content://sms/
尝试内容观察者
它的工作正常,但onChange()
被调用两次,参数完全相同。我曾尝试检查时间戳,但它们是相同的,就像我设置的类型和其他所有参数一样。
从我所看到的情况来看,这是一个常见的问题,但不是我见过的任何一个问题。
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
querySMS();
}
protected void querySMS() {
Cursor cur = getContentResolver().query(u, null, null, null, null);
cur.moveToNext(); // this will make it point to the first record, which is the last SMS sent
String type = cur.getString(cur.getColumnIndex("type"));
String body = cur.getString(cur.getColumnIndex("body")); //content of sms
String add = cur.getString(cur.getColumnIndex("address")); //phone num
if (type.equals("1")) {
if (add.equals(Test.SENDER)) {
String[] bodys = body.split(" ", 7);
if (bodys[0].equals("test")) {
test = true;
}
cat = bodys[1];
level = bodys[2];
urgency = bodys[3];
certainty = bodys[4];
carrier = bodys[5];
message = bodys[6];
final Intent intent = new Intent(context, AlertActivity.class);
Bundle b = new Bundle();
b.putString("title", cat);
b.putString("certainty", certainty);
b.putString("urgency", urgency);
b.putString("level", level);
b.putString("message", message);
b.putBoolean("test", test);
intent.putExtras(b);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
carrierName = manager.getNetworkOperatorName();
if (carrierName.replaceAll(" ", "").equals(carrier)) {
context.startActivity(intent);
} else {
//testing
Toast.makeText(context, carrierName.replaceAll(" ", ""), Toast.LENGTH_LONG).show();
}
}
}
}
由于onChange()
被解雇两次,我也会收到两个警报。我无法为我的生活找到解决方法。
答案 0 :(得分:4)
如果两者相同:
存储收到的每条消息
将它与之前收到的消息进行比较
如果没有找到,请处理
如果找到,请丢弃该消息
存储的消息的生命周期应该是无穷小的,5个消息的小循环缓冲区应该没问题。
答案 1 :(得分:4)
这是我的代码,它对我来说很好用
public class SmsObserver extends ContentObserver {
private Context context;
private static int initialPos;
private static final String TAG = "SMSContentObserver";
private static final Uri uriSMS = Uri.parse("content://sms/sent");
public SmsObserver(Handler handler, Context ctx) {
super(handler);
context = ctx;
initialPos = getLastMsgId();
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
queryLastSentSMS();
}
public int getLastMsgId() {
Cursor cur = context.getContentResolver().query(uriSMS, null, null, null, null);
cur.moveToFirst();
int lastMsgId = cur.getInt(cur.getColumnIndex("_id"));
Log.i(TAG, "Last sent message id: " + String.valueOf(lastMsgId));
return lastMsgId;
}
protected void queryLastSentSMS() {
new Thread(new Runnable() {
@Override
public void run() {
Cursor cur =
context.getContentResolver().query(uriSMS, null, null, null, null);
if (cur.moveToNext()) {
try {
if (initialPos != getLastMsgId()) {
// Here you get the last sms. Do what you want.
String receiver = cur.getString(cur.getColumnIndex("address"));
System.out.println(" Receiver Ph no :"+receiver);
// Then, set initialPos to the current position.
initialPos = getLastMsgId();
}
} catch (Exception e) {
// Treat exception here
}
}
cur.close();
}
}).start();
}
}//End of class SmsObserver
答案 2 :(得分:3)
您可以保存上一封邮件的ID,并将其与cur
中onChange
返回的邮件的ID进行比较。如果ID相同,那么你可以简单地忽略该消息。
// might contain mistakes, but you'll get the idea:
protected void querySMS() {
Cursor cur = getContentResolver().query(u, null, null, null, null);
cur.moveToNext();
if (lastId == cur.getLong(cur.getColumnIndex("_id")))
return;
lastId = cur.getLong(cur.getColumnIndex("_id"));
... //continue as it was
}
然而 - 如果用户选择此选项(接收设置 - 禁用其他消息通知),GO短信仅阻止其他应用接收广播 - 所以如果用户不希望其他应用打扰他 - 我认为不这样做是个好主意。
答案 3 :(得分:0)
我只是使用SharedPreference来记录最后的短信息(例如:id\type
...)。如果它是相同的,我会return
。