Android ConnectivityService - "onUnhold" not called

281 views Asked by At

I'm trying to use self-managed ConnectivityService to manage calls in-app - https://developer.android.com/guide/topics/connectivity/telecom/selfManaged

It is poorly documented and there are hardly any examples on the web, however, I've managed to make it work quite well except for one scenario - getting "onUnhold" callback in one case.

So, we are in a self-managed VoIP call on my phone (A), then we receive a regular GSM call from the second phone (B), and when I answer this on phone A, I get "onHold()" callback in my Connection object where I can put my VoIP call on hold.

Then, when I end this GSM call from phone A, I got "onUnhold()" callback from where I can set my VoIP call to be active again, BUT when the call will be ended by phone B, there is no callback whatsoever, nothing in my Connection object or even in my ConnectionService.

There is even an issue in the Android tracker that describes the exact same thing and it's really well documented, with examples on GitHub and all: https://issuetracker.google.com/issues/223757078 but Google claims that this is an expected behavior.

How can I "unHold" my VoIP connection when the remote user will end the call then? I've tried to listen PhoneStateListener/TelephonyCallback, but there I get states also from my own call and I can't distinguish if the state was from my or GSM call...

1

There are 1 answers

0
asat On

i absolutely agree with you about how its documented and examples, so i was needed to spend twice time then i was expected, digging into 3 big open source projects in order to implement Telecom functionality.
But finally encounter exactly the same problem as you described.
And TelecomManager having isInCall() which useless in my case, with which i can not distinguish my call and GSM call.
But TelecomManager having isInManagedCall(), for my call false, for GSM call true.
Here is method of MyConnection class which extends Connection, TelecomHelper is just my helper class to call TelecomManager methods.

@Override
public void onCallAudioStateChanged(CallAudioState state)
{
    if(getState() == Connection.STATE_HOLDING)
    {
        if(!engine().getTelecomHelper().isInManagedCall())
        {
            new Handler().postDelayed(new Runnable(){
                @Override
                public void run()
                {
                    if(getState() == Connection.STATE_HOLDING)
                    {
                        if(!engine().getTelecomHelper().isInManagedCall())
                        {
                            engine().hold(false);// my application logic
                            setActive();
                        }
                    }
                }
            },1000);
        }
    }
}

The principle is, onCallAudioStateChanged is called every time GSM call completed, state is checking two times with delay, because onCallAudioStateChanged() called earlier than onUnhold() in good scenario.
Usuallly, onUnhold() calling almost immediately after onCallAudioStateChanged(), so instead of 1000ms delay may be used much lesser value.
At least this solution is working for me.