简体   繁体   中英

Android application using BroadcastReceiver right way

I want to implement functionality of call registration in my Android application. For this need I implemented BroadcastReceiver this way:

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);
    }
}

}

As you could see, on Receive event I'm registering PhoneStateListener, which starts to monitor changing call states.

Firts call to phone after restart application works correctly. I could see events as I expected:

TelephonyManager.CALL_STATE_RINGING

then

TelephonyManager.CALL_STATE_IDLE if there were not offhook event.

But after second call I could see that events are doubling. I could see double and triple of events of TelephonyManager.CALL_STATE_IDLE . And it seems that this events processed in independent threads because callMonitoring.clearState() doesn't prevent from second string Log.d("MyPhoneListener","api params: phone [" + incomingNumber + "]; duration [" + duration + "]; callType [" + callType.getCallType() + "]; callStatus [" + callStatus.getCallStatus() + "]");.

How can I "reset" the state of my BroadcastReceiver?

Or maybe I've missed something crusual?

You are confusing two things. 1. The PhoneStateListener API , which a running application can make use of to monitor various telephony state items. 2. The phone state broadcast , which can be used by a running or non-running application to be notified of changes to the phone state.

You should NOT be registering a PhoneStateListener within a BroadcastReceiver in this manner. Look at how the ACTION_PHONE_STATE_CHANGED broadcast works; that should be enough to accomplish your goal.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM