#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!