Android SIP 呼叫响起,然后收到 ENETUNREACH(网络无法访问)

问题描述 投票:0回答:2

我尝试使用

android.net.sip.SipManager
将出站 SIP 呼叫添加到 Android 应用程序中,我接到了
onRingBack
的电话,但是当对方接听电话时,我接到了
onError
的电话,代码为 -4 并显示消息
android.system.ErrnoException: sendto failed: ENETUNREACH (Network is unreachable) 
.

我怀疑这是某种防火墙或网络问题,因为根据我使用的网络,我在过程中的不同点收到 ENETUNREACH 错误。启用 VPN 后,我会在

onRingBack
回调之前收到它。使用公共 WiFi 网络,我根本不会收到
onError
回调,只是在
onRingBack
之后没有收到任何回调。通过我的个人 WiFi 网络,我得到了如上所述的
onError
但不知怎的,LinPhoneAndroid 应用程序没有这个问题,所以必须有一种方法来解决这个问题。

为了进行测试设置,我在 linphone.org 创建了两个帐户:

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

我在 iPhone 11 上使用第一个帐户和 LinPhone iOS 应用程序。我在装有 Android 12 的 Google Pixel 4a 上使用第二个帐户和 LinPhone Android 应用程序。我验证了我可以成功从 AndroidiOS 拨打电话使用这些 LinPhone 应用程序。

然后我在 Android 上编写了自己的应用程序来调用 iPhone。它成功注册到 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")
                }

            })

然后,我可以使用

sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, audioCallListener, 30)
向 iPhone 发起出站呼叫,iPhone 实际上会响铃并可以应答呼叫,从而启动 LinPhone iOS 应用程序并显示正在进行的呼叫计时器。 **当 iPhone 开始响铃时,我的 Android 代码会回调
onRingingBack
。但是当 iPhone 接听电话时,它会接到一个拨打
onError
的电话,代码为 -4 并发送消息
sendto failed: ENETUNREACH (Network is unreachable)

以下是发起调用并实现回调的完整代码:

        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)
                }
        }
android sip voip-android
2个回答
0
投票

不幸的是,答案是放弃使用这些 API。谷歌有:

此接口在 API 级别 31 中已弃用。不再支持 SipManager 和相关类,并且不应将其用作未来 VOIP 应用程序的基础。

参见这里


0
投票

当我的电脑通过 VPN 连接时,端点可以访问,而我的手机却不能访问,这种情况就发生在我身上。将您的手机连接到 VPN 或使用反向网络共享,以便您的手机通过 PC 连接 - 请参阅 https://github.com/Genymobile/gnirehtet

© www.soinside.com 2019 - 2024. All rights reserved.