问题描述
我目前正在构建一个垃圾邮件阻止应用程序,作为一个有趣的项目,以使Android开发更好,并且遇到了这个奇怪的错误。
我有一个广播接收器设置,用于侦听呼叫状态的变化,并具有逻辑来检查呼叫是否传入,如果该号码不在用户的联系人列表或“白名单”中,则基本上结束呼叫数据库中保存的已批准号码的数量。但是,即使在通话结束后,也会继续多次呼叫接收方(有时8次或更多次),并且通常会在将通话状态设置为振铃的情况下再次通话(尽管通话已经结束)。
基本上,我正在尝试跟踪每个未知号码拨打电话的次数,但是对于每次通话,它将记录为2到6个通话中的任何一个。
这是我设置的onReceive函数:
public void onReceive(final Context con,Intent intent) {
System.out.println(intent);
final TelephonyManager telephony = (TelephonyManager) con.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(new PhonestateListener() {
@RequiresApi(api = Build.VERSION_CODES.P)
@Override
public void onCallStateChanged(int state,String incomingNumber) {
super.onCallStateChanged(state,incomingNumber);
System.out.print(state);
//Toast.makeText(con,incomingNumber,Toast.LENGTH_LONG).show();
if (TelephonyManager.CALL_STATE_RINGING == state) {
checkIfNumberInContacts(con,telephony,state);
}
}
},PhonestateListener.LISTEN_CALL_STATE);
}
这是自定义功能,用于检查传入的电话号码是否在联系人/列入白名单的电话中并结束呼叫:
@RequiresApi(api = Build.VERSION_CODES.P)
public void checkIfNumberInContacts(Context con,String incomingNumber,TelephonyManager telephony,int state) {
db = Room.databaseBuilder(con,SpamBlockerDB.class,"spamblocker.db").createFromAsset("databases/spamblocker.db").allowMainThreadQueries().build();
FilteredCalls call = new FilteredCalls();
call.calltime = Calendar.getInstance().getTime().toString();
call.deleted = 0;
call.number = incomingNumber;
call.whitelisted = 0;
call.callcount = 1;
List<FilteredCalls> allCalls = db.callsDao().getAll();
boolean callerExistsInDB = false;
for (FilteredCalls item : allCalls) {
if (incomingNumber.equals(item.number)) {
callerExistsInDB = true;
String updatedTime = Calendar.getInstance().getTime().toString();
db.callsDao().updateCallTime(updatedTime,item.recID);
}
if (TelephonyManager.CALL_STATE_RINGING == state) {
int currentCount = db.callsDao().getCallCount(item.recID);
db.callsDao().updateCallCount(currentCount + 1,item.recID);
}
}
ContentResolver contentResolver = con.getContentResolver();
Uri uri = Uri.withAppendedpath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,Uri.encode(incomingNumber));
String contact = "";
Cursor c = contentResolver.query(uri,new String[]{ContactsContract.PhoneLookup.HAS_PHONE_NUMBER},null,null);
if (c != null) {
if (c.movetoFirst()) {
do {
contact = c.getString(c.getColumnIndex("NUMBER"));
} while (c.movetoNext());
}
}
if (contact == "" && !checkIfNumberIsWhitelisted(con,incomingNumber)) {
TelecomManager telecomManager = (TelecomManager) con.getSystemService(Context.TELECOM_SERVICE);
telecomManager.endCall();
if (!callerExistsInDB) {
db.callsDao().insert(call);
}
}
}
有什么想法为什么broadCast接收器被呼叫两次以上(一次进入,挂断一次),以及为什么当其后再被呼叫时仍然认为电话在响铃?
提前了解帮助。
解决方法
当电话状态更改时,有两种获取回调的方法:PhoneStateListener
和监听BroadcastReceiver
的{{1}}。
您似乎将两种方法混合在一起,这意味着每当调用BroadcastReceiver时,您都在注册另一个新android.intent.action.PHONE_STATE
,因此您会不断添加更多听众做同样的事情。
我建议完全不使用PhoneStateListener
,而只使用PhoneStateListener
方法,该方法可以通过BroadcastReceiver
进行设置,即使应用处于睡眠状态也可以调用它
请参阅本教程:https://medium.com/@saishaddai/how-to-know-when-a-device-is-ringing-in-android-57e516d0ab42