Java Sms ContentObserver onChange()多次激发
我知道这个问题已经被问了很多次了,但从我所看到的情况来看,没有人能给出有效的答案 我正在开发一个截获短信的应用程序,根据发送时间,会弹出一个自定义警报。我让它与广播接收器完美配合,但是如果用户安装了GOSM,则不会调用Java Sms ContentObserver onChange()多次激发,java,android,contentobserver,Java,Android,Contentobserver,我知道这个问题已经被问了很多次了,但从我所看到的情况来看,没有人能给出有效的答案 我正在开发一个截获短信的应用程序,根据发送时间,会弹出一个自定义警报。我让它与广播接收器完美配合,但是如果用户安装了GOSM,则不会调用onReceive()方法,因为GOSM会在它到达我的应用程序之前中止它 为了解决这个问题,我尝试在content://sms/ 它工作正常,但是调用了两次onChange(),参数完全相同。我试着检查时间戳,但它们是一样的,我设置的类型和其他参数也是一样的 从我所看到的,这是一个
onReceive()
方法,因为GOSM会在它到达我的应用程序之前中止它
为了解决这个问题,我尝试在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()
被触发了两次,我也收到了两个警报。我一辈子都想不出解决这个问题的办法。如果两者相同:存储接收到的每条消息
将其与以前接收的消息进行比较
如果未找到,则处理
如果找到,则丢弃该消息
存储的消息的寿命应该是无限小的,一个5条消息的小循环缓冲区就可以了。您可以保存最后一条消息的id,并将其与
onChange
中的cur
返回的消息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 SMS只会阻止其他应用程序接收广播-因此,如果用户不希望其他应用程序打扰他-我认为最好不要这样做。这是我的代码,对我来说很好
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
我只是使用SharedReference注释最后的SMS信息(比如:
id\type
…)。如果是相同的,我将返回
指向其他(不完整)答案的链接将很有帮助。尽管消息只收到一次。它不会再来两次。tbh,我甚至不知道第二个onChange
是从什么触发的。啊。把你的想法和我的想法结合起来,我成功了。我想我第一次读的时候误解了你的意思。我创建了一个静态的arrayList
,并使用它进行检查。if(!ids.contains(id)){ids.add(id);context.startActivity(intent);}
Im使用的应用程序永远都不应该被忽略。它可以预先安装在设备上,并且完全优先于手机上当前运行的任何其他设备。我做了一些与此类似的事情,如果你看下面答案的评论,你会看到。你明白,你发布的代码片段在应用程序中使用之前应该有很长很长的路要走,是不是?哦,是的,当然。我才刚开始这个项目。还有很长的路要走