Я хочу реализовать функциональность регистрации вызовов в моем приложении Android. Для этого я реализовал BroadcastReceiver следующим образом:
public class IncomingCall extends BroadcastReceiver {
//private AppPhoneStateListener phoneStateListener;
private TelephonyManager telephonyManager;
private HashMap<String, AppPhoneStateListener> appPhoneStateListenerHashMap = new HashMap<>();
@Override
public void onReceive(Context context, Intent intent) {
try {
// Create manager for listener registration
AppPhoneStateListener phoneStateListener = new AppPhoneStateListener();
telephonyManager = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
// Register listener for LISTEN_CALL_STATE
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e) {
Crashlytics.logException(e);
}
}
private class AppPhoneStateListener extends PhoneStateListener {
private CallMonitoring callMonitoring = new CallMonitoring();
@Override
public void onCallStateChanged(int state, String incomingNumber) {
// Service only for child device
Role role = User.getRole();
if (role == Role.parent) return;
Log.d("MyPhoneListener","state [" + state + "]");
if (state == TelephonyManager.CALL_STATE_RINGING) {
callMonitoring.registerChangeState(state);
if (!appPhoneStateListenerHashMap.containsKey(incomingNumber)) {
appPhoneStateListenerHashMap.put(incomingNumber, this);
} else {
telephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
}
//Log.d("MyPhoneListener","saved call states [" + callMonitoring.showCallStates() + "]");
}
if (appPhoneStateListenerHashMap.containsKey(incomingNumber)) {
if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
callMonitoring.registerChangeState(state);
//Log.d("MyPhoneListener","saved call states [" + callMonitoring.showCallStates() + "]");
}
if (state == TelephonyManager.CALL_STATE_IDLE) {
//Log.d("MyPhoneListener","saved call states [" + callMonitoring.showCallStates() + "]");
// There was incoming call then we have call attachCall api method
if (callMonitoring.wasIncomingCall()) {
long duration = callMonitoring.getLastActionDuration();
CallType callType = callMonitoring.getCallType();
CallStatus callStatus = callMonitoring.getCallStatus();
// Logging to debug
Log.d("MyPhoneListener","api params: phone [" + incomingNumber + "]; duration [" + duration + "]; callType [" + callType.getCallType() + "]; callStatus [" + callStatus.getCallStatus() + "]");
// Call api
// Unregister listener for LISTEN_CALL_STATE
unsubscribeCallListener(incomingNumber);
}
// Return call monitoring call to initial state
callMonitoring.clearState();
}
}
}
private void unsubscribeCallListener(String incomingNumber) {
appPhoneStateListenerHashMap.remove(incomingNumber);
telephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
}
}
}
Как вы могли видеть, при получении события я регистрирую PhoneStateListener, который начинает отслеживать изменение состояний вызова.
Первый звонок на телефон после перезагрузки приложения работает корректно. Я мог видеть события, как я ожидал:
TelephonyManager.CALL_STATE_RINGING
1011 * тогда *
TelephonyManager.CALL_STATE_IDLE
если не было события вне очереди.
Но после второго звонка я увидел, что события удваиваются. Я мог видеть двойные и тройные события TelephonyManager.CALL_STATE_IDLE
. И кажется, что эти события обрабатываются в независимых потоках, потому что callMonitoring.clearState()
не мешает второй строке Log.d("MyPhoneListener","api params: phone [" + incomingNumber + "]; duration [" + duration + "]; callType [" + callType.getCallType() + "]; callStatus [" + callStatus.getCallStatus() + "]");.
Как я могу "сбросить" состояние моего BroadcastReceiver?
Или, может быть, я пропустил что-то грубое?