通话结束后,TelephonyManager的通话状态仍设置为CALL_STATE_RINGING

问题描述

我目前正在构建一个垃圾邮件阻止应用程序,作为一个有趣的项目,以使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