【问题标题】:TelephonyManager call state still set at CALL_STATE_RINGING after call has been ended通话结束后,TelephonyManager 通话状态仍设置为 CALL_STATE_RINGING
【发布时间】:2020-08-23 04:30:52
【问题描述】:

我目前正在构建一个垃圾邮件拦截应用程序作为一个有趣的项目,以便更好地进行 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, incomingNumber, 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);
        }
    }
}

知道为什么广播接收器被呼叫了两次以上(一次来电,一次挂机),为什么当它被呼叫时,它仍然认为电话在响铃?

提前感谢帮助。

【问题讨论】:

    标签: java android broadcastreceiver telephonymanager


    【解决方案1】:

    当手机状态改变时,有两种方法可以得到回调:PhoneStateListener 和一个监听android.intent.action.PHONE_STATEBroadcastReceiver

    看起来您将这两种方法混合在一起,这意味着无论何时调用 BroadcastReceiver,您都在注册另一个新的PhoneStateListener,因此您不断添加越来越多的侦听器做同样的事情。

    我建议完全不要使用PhoneStateListener,而只使用BroadcastReceiver 方法,可以通过AndroidManifest 进行设置,这样即使应用程序处于睡眠状态也可以调用它。

    查看本教程:https://medium.com/@saishaddai/how-to-know-when-a-device-is-ringing-in-android-57e516d0ab42

    【讨论】:

    • 非常感谢!我查看了您给我的链接并稍微修改了我的代码,现在它可以完美运行,所以我已将您的评论标记为答案。您的回答对于广播接收器每次调用时都会注册一个新的 Phonestatelistener 非常有意义。感谢您的帮助,帮助我了解更多关于 Android 开发的知识!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多