0

我正在尝试使用 将出站 SIP 呼叫添加到 Android 应用程序中android.net.sip.SipManageronRingBack但当对方接听电话时,我会收到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 应用程序的第二个帐户。我验证我可以使用这些 LinPhone 应用程序成功地从Android拨打iOS电话。

然后我在 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")
                }

            })

然后,我可以使用 向 iPhone 发起出站呼叫,sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, audioCallListener, 30)iPhone 实际上会响铃并且可以接听启动 LinPhone iOS 应用程序并显示呼叫进行中计时器的呼叫。**当 iPhone 开始响铃时,我的 Android 代码会回调到onRingingBack. 但是当 iPhone 接听电话时,它会收到一个onError带有代码 -4 和 d 消息的电话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)
                }
        }
4

0 回答 0