Состояние вызова TelephonyManager по-прежнему устанавливается в CALL_STATE_RINGING после завершения вызова

#java #android #broadcastreceiver #telephonymanager

#java #Android #broadcastreceiver #telephonymanager

Вопрос:

В настоящее время я создаю приложение для блокировки нежелательных вызовов в качестве забавного проекта, чтобы улучшить разработку Android, и столкнулся с этой странной ошибкой.

У меня есть настройка широковещательного приемника для прослушивания изменений в состоянии вызова и логика для проверки, является ли вызов входящим или нет, и в основном завершает вызов, если номер отсутствует в списке контактов пользователя или в «белом списке» утвержденных номеров, хранящихся в базе данных. Однако даже после завершения вызова получатель продолжает вызываться несколько раз (иногда 8 или более раз) и часто вызывается с состоянием вызова, установленным как ringing (опять же, несмотря на то, что вызов был завершен).

В принципе, я пытаюсь отслеживать, сколько раз каждый неизвестный номер вызывает телефон, но для каждого отдельного вызова он записывает его как от 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 == "" amp;amp; !checkIfNumberIsWhitelisted(con, incomingNumber)) {
        TelecomManager telecomManager = (TelecomManager) con.getSystemService(Context.TELECOM_SERVICE);
        telecomManager.endCall();

        if (!callerExistsInDB) {
            db.callsDao().insert(call);
        }
    }
}
  

Есть идеи, почему широковещательный приемник вызывается более двух раз (один раз для входящих, один раз для отбоя), и почему, когда он вызывается в последующие разы, он все еще думает, что телефон звонит?

Заранее благодарен за помощь.

Ответ №1:

Есть два способа получить обратные вызовы при изменении состояния телефона: PhoneStateListener и BroadcastReceiver который прослушивает android.intent.action.PHONE_STATE .

Похоже, что вы смешиваете два метода вместе, что означает, что всякий раз, когда вызывается ваш BroadcastReceiver, вы регистрируете другой новый PhoneStateListener , поэтому вы продолжаете добавлять все больше и больше слушателей, которые делают то же самое.

Я бы рекомендовал не использовать PhoneStateListener вообще и использовать только BroadcastReceiver подход, который можно настроить с помощью AndroidManifest , который позволяет вызывать его, даже когда приложение находится в спящем режиме.

Смотрите это руководство:https://medium.com/@saishaddai/how-to-know-when-a-device-is-ringing-in-android-57e516d0ab42

Комментарии:

1. Большое вам спасибо! Я просмотрел ссылку, которую вы мне дали, и немного подправил свой код, и теперь он работает отлично, поэтому я пометил ваш комментарий как ответ. Ваш ответ имеет большой смысл в том, что широковещательный приемник регистрирует новый Phonestatelistener при каждом его вызове. Спасибо за вашу помощь и то, что вы помогли мне узнать больше о разработке Android!