简体   繁体   中英

Android SIP call rings then gets ENETUNREACH (Network is unreachable)

I am trying to add outbound SIP calling into an Android app using android.net.sip.SipManager , I get a call to onRingBack but when the other side answers the call I get a call to onError with code -4 and message android.system.ErrnoException: sendto failed: ENETUNREACH (Network is unreachable) .

I suspect that this is some kind of firewall or network issue because depending on the network I use, I get the ENETUNREACH error at different points in the process. With my VPN enabled, I get it before the onRingBack callback. With a public WiFi network, I never get the onError callback at all, I just get no callbacks after onRingBack . And with my personal WiFi network, I get the onError as described above. Yet somehow the LinPhoneAndroid app does not have this problem, so there must be a way to code around this.

For my test setup this, I created two accounts at linphone.org:

  • sip:[myphonenumber]@sip.linphone.org // iPhone
  • sip:[myusername]@sip.linphone.org // Android

I use the first account with the LinPhone iOS app on my iPhone 11. I use the second account with the LinPhone Android app on my Google Pixel 4a with Android 12. I verified I can successfully make calls from Android to iOS using these LinPhone apps.

I then coded my own app on Android to call the iPhone. It successfully registers with the SIP server with:

            sipProfile = SipProfile.Builder(username, domain).setPassword(password).build()
            val intent = Intent()
            intent.action = "android.SipDemo.INCOMING_CALL"
            val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, Intent.FILL_IN_DATA)
            sipManager.open(sipProfile, pendingIntent, null)
            sipManager.setRegistrationListener(sipProfile.uriString, object: SipRegistrationListener {
                override fun onRegistering(localProfileUri: String?) {
                    Log.d(TAG, "Registering")
                }

                override fun onRegistrationDone(localProfileUri: String?, expiryTime: Long) {
                    registrationExpiration = Date(expiryTime)
                    ...
                    Log.d(TAG, "Registration done.  LocalProfileUri: $localProfileUri Expiry Time: ${registrationExpiration}")
                }

                override fun onRegistrationFailed(
                    localProfileUri: String?,
                    errorCode: Int,
                    errorMessage: String?
                ) {
                    Log.d(TAG, "Registration failed.  LocalProfileUri: $localProfileUri,  Error code: $errorCode, Error MessagE: $errorMessage")
                }

            })

I can then initiate an outbound call to the iPhone with sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, audioCallListener, 30) , and the iPhone actually rings and can answer the call which launches the LinPhone iOS app and shows a call in progress timer. **When the iPhone starts ringing, my Android code gets a callback to onRingingBack . But when the iPhone answers the call it gets a call to onError with code -4 an d message sendto failed: ENETUNREACH (Network is unreachable)

Here is the full code that initiates the call and implements the callbacks:

        audioCallListener = object: SipAudioCall.Listener() {
            public override fun onError(
                call: SipAudioCall?,
                errorCode: Int,
                errorMessage: String?
            ) {
                super.onError(call, errorCode, errorMessage)
                Log.d(TAG, "Error making call code: $errorCode, message: $errorMessage")

            }

            public override fun onReadyToCall(call: SipAudioCall?) {
                Log.d(TAG, "ready to call")
                super.onReadyToCall(call)
            }

            public override fun onRingingBack(call: SipAudioCall?) {
                Log.d(TAG, "onRingingBack")
                super.onRingingBack(call)
            }

            public override fun onCalling(call: SipAudioCall?) {
                Log.d(TAG, "onCalling")
                super.onCalling(call)
            }

            public override fun onCallHeld(call: SipAudioCall?) {
                Log.d(TAG, "onCallHeld")
                super.onCallHeld(call)
            }

            public override fun onCallBusy(call: SipAudioCall?) {
                Log.d(TAG, "onCallBusy")
                super.onCallBusy(call)
            }

            public override fun onChanged(call: SipAudioCall?) {
                val state = call?.state ?: -1
                Log.d(TAG, "onChanged state: ${state}")
                super.onChanged(call)
            }
            public override fun onRinging(call: SipAudioCall?, caller: SipProfile?) {
                Log.d(TAG, "Ringing...")
                super.onRinging(call, caller)
            }
            public override fun onCallEstablished(call: SipAudioCall) {
                mediaPlayer?.stop()
                call.startAudio()
                call.setSpeakerMode(true)
                call.toggleMute()
                Log.d(TAG, "Calls started")
                super.onCallEstablished(call)
            }

            public override fun onCallEnded(call: SipAudioCall) {
                Log.d(TAG, "Call ended")
                super.onCallEnded(call)
            }
        }
        GlobalScope.launch {
                Log.d(TAG, "Making call from ${sipProfile.getUriString()} to ${sipAddress}")
                try {
                    lastCall = sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, audioCallListener, 30);
                }
                catch (e: SipException) {
                    Log.e(TAG, "Call failed", e)
                }
        }

Unfortunately, the answer is to give up on using these APIs. Google has:

This interface was deprecated in API level 31. SipManager and associated classes are no longer supported and should not be used as the basis of future VOIP apps.

See here

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