简体   繁体   English

Android SIP 呼叫响铃然后得到 ENETUNREACH(网络不可达)

[英]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) .我正在尝试使用android.net.sip.SipManager将出站 SIP 呼叫添加到 Android 应用程序中,我接到了onRingBack的电话,但是当对方接听电话时,我接到了onError的电话,代码为 -4 和消息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.我怀疑这是某种防火墙或网络问题,因为根据我使用的网络,我在过程中的不同点会收到 ENETUNREACH 错误。 With my VPN enabled, I get it before the onRingBack callback.启用我的 VPN 后,我会在onRingBack回调之前得到它。 With a public WiFi network, I never get the onError callback at all, I just get no callbacks after onRingBack .使用公共 WiFi 网络,我根本不会收到onError回调,我只是在onRingBack之后没有收到回调。 And with my personal WiFi network, I get the onError as described above.通过我的个人 WiFi 网络,我得到了如上所述的onError Yet somehow the LinPhoneAndroid app does not have this problem, so there must be a way to code around this.然而不知何故,LinPhoneAndroid 应用程序没有这个问题,所以必须有一种方法来解决这个问题。

For my test setup this, I created two accounts at linphone.org:对于我的测试设置,我在 linphone.org 创建了两个帐户:

  • sip:[myphonenumber]@sip.linphone.org // iPhone sip:[myphonenumber]@sip.linphone.org // iPhone
  • sip:[myusername]@sip.linphone.org // Android 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 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.然后我在 Android 上编写了自己的应用程序来调用 iPhone。 It successfully registers with the SIP server with:它成功地向 SIP 服务器注册:

            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.然后,我可以使用sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, audioCallListener, 30)向 iPhone 发起出站呼叫,iPhone 实际响铃并且可以接听启动 LinPhone iOS 应用程序的呼叫并显示正在进行的呼叫计时器。 **When the iPhone starts ringing, my Android code gets a callback to onRingingBack . **当 iPhone 开始响铃时,我的 Android 代码会回调到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)但是当 iPhone 接听电话时,它会使用代码 -4 调用onError并且发送消息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.不幸的是,答案是放弃使用这些 API。 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.此接口在 API 级别 31 中已弃用。不再支持 SipManager 和相关类,不应将其用作未来 VOIP 应用程序的基础。

See here这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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