Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/185.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Webrtc为语音聊天应用创建网格架构_Android_Webrtc Android - Fatal编程技术网

Android Webrtc为语音聊天应用创建网格架构

Android Webrtc为语音聊天应用创建网格架构,android,webrtc-android,Android,Webrtc Android,我正在尝试创建一个android语音聊天应用程序,4人一组,4人可以互相交谈。这可以使用android web RTC中的mesh架构来完成。我已经创建了所有先决条件,即设置转弯服务器、信号服务器和android应用程序代码。这里的问题是,我不能让它为超过两个人工作。这里s发生的事情,最初是一个用户(a)加入一个房间。然后另一个用户(B)加入房间。SDP报价、应答和ICE候选人成功交换并建立连接。A和B都可以相互交谈。当第三个用户(C)加入房间时,问题开始出现。当C进入房间后,SDP报价、答案和

我正在尝试创建一个android语音聊天应用程序,4人一组,4人可以互相交谈。这可以使用android web RTC中的mesh架构来完成。我已经创建了所有先决条件,即设置转弯服务器、信号服务器和android应用程序代码。这里的问题是,我不能让它为超过两个人工作。这里
s发生的事情,最初是一个用户(a)加入一个房间。然后另一个用户(B)加入房间。SDP报价、应答和ICE候选人成功交换并建立连接。AB都可以相互交谈。当第三个用户(C)加入房间时,问题开始出现。当C进入房间后,SDP报价、答案和ICE候选人将与ABC交换,然后BC成功连接,他们都可以互相交谈,而B则与A断开连接,表示A听不见BB听不见A,虽然它们在启动时已成功连接,但用户A以单向连接到C,表示C可以收听A,而A不能收听C

我想不出来。任何帮助都是非常感激的

我的RTCClient类中有此代码

class RTCClient(context: Application, mSocketId: String) {

    val socketId: String = mSocketId
    private val listOfServers = ArrayList<IceServer>()

    init {
        initPeerConnectionFactory(context)
        createServeList()
    }

    private fun createServeList() {

        listOfServers.add(IceServer.builder("stun:stun.services.mozilla.com").createIceServer())
        listOfServers.add(IceServer.builder("stun:stun.l.google.com:19302").createIceServer())
        listOfServers.add(
            IceServer.builder("turn:ip:port").setUsername("usernmae")
                .setPassword("password").createIceServer()
        )
    }

    private val peerConnectionFactory by lazy { buildPeerConnectionFactory() }

    private val localAudioSource by lazy { peerConnectionFactory.createAudioSource(MediaConstraints()) }
    private val peerConnection by lazy { buildPeerConnection(peerConnectionObserver) }


    private fun initPeerConnectionFactory(context: Application) {
        val options = PeerConnectionFactory.InitializationOptions.builder(context)
            .setEnableInternalTracer(true)
            .setFieldTrials("WebRTC-H264HighProfile/Enabled/")
            .createInitializationOptions()
        PeerConnectionFactory.initialize(options)
    }


    private fun buildPeerConnectionFactory(): PeerConnectionFactory {
        return PeerConnectionFactory
            .builder()
            .setOptions(PeerConnectionFactory.Options().apply {
                disableEncryption = true
                disableNetworkMonitor = true
            })
            .createPeerConnectionFactory()
    }

    private fun buildPeerConnection(observer: PeerConnection.Observer) =
        peerConnectionFactory.createPeerConnection(
            listOfServers,
            observer
        )

    fun startLocalAudioSource(): ConnectionFactory {
        val audioTrack = peerConnectionFactory.createAudioTrack("ARDAMSa0", localAudioSource)
        val localMediaStream = peerConnectionFactory.createLocalMediaStream("ARDAMS")
        localMediaStream.addTrack(audioTrack)
        peerConnection?.addStream(localMediaStream)
        return ConnectionFactory(peerConnectionFactory, peerConnection)
    }

    private fun PeerConnection.call(sdpObserver: SdpObserver) {
        val constraints = MediaConstraints().apply {
            mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveVideo", "false"))
        }

        createOffer(object : SdpObserver by sdpObserver {
            override fun onCreateSuccess(desc: SessionDescription?) {

                setLocalDescription(object : SdpObserver {
                    override fun onSetFailure(p0: String?) {
                    }

                    override fun onSetSuccess() {
                    }

                    override fun onCreateSuccess(p0: SessionDescription?) {
                    }

                    override fun onCreateFailure(p0: String?) {
                    }
                }, desc)
                sdpObserver.onCreateSuccess(desc)
            }
        }, constraints)
    }

    private fun PeerConnection.answer(sdpObserver: SdpObserver) {
        val constraints = MediaConstraints().apply {
            mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveVideo", "false"))
        }

        createAnswer(object : SdpObserver by sdpObserver {
            override fun onCreateSuccess(p0: SessionDescription?) {
                setLocalDescription(object : SdpObserver {
                    override fun onSetFailure(p0: String?) {
                    }

                    override fun onSetSuccess() {
                    }

                    override fun onCreateSuccess(p0: SessionDescription?) {
                    }

                    override fun onCreateFailure(p0: String?) {
                    }
                }, p0)
                sdpObserver.onCreateSuccess(p0)
            }
        }, constraints)
    }

    fun call(sdpObserver: SdpObserver) = peerConnection?.call(sdpObserver)

    fun answer(sdpObserver: SdpObserver) = peerConnection?.answer(sdpObserver)

    fun onRemoteSessionReceived(sessionDescription: SessionDescription) {
        peerConnection?.setRemoteDescription(object : SdpObserver {
            override fun onSetFailure(p0: String?) {
            }

            override fun onSetSuccess() {
            }

            override fun onCreateSuccess(p0: SessionDescription?) {
            }

            override fun onCreateFailure(p0: String?) {
            }
        }, sessionDescription)
    }

    fun addIceCandidate(iceCandidate: IceCandidate?) {
        peerConnection?.addIceCandidate(iceCandidate)
    }

    val sdpObserver = object : AppSdpObserver() {
        override fun onCreateSuccess(p0: SessionDescription?) {
            super.onCreateSuccess(p0)
            SocketConnection.socket.emit("offer", BaseClass.gSon.toJson(p0), socketId)
        }
    }

    private val peerConnectionObserver = object : PeerConnectionObserver() {
        override fun onIceCandidate(p0: IceCandidate?) {
            super.onIceCandidate(p0)
            SocketConnection.socket.emit("ice", BaseClass.gSon.toJson(p0), socketId)
        }
    }   
}
这是对等连接观察者类

open class PeerConnectionObserver : PeerConnection.Observer {
    override fun onIceCandidate(p0: IceCandidate?) {
        Timber.tag("VoiceChatFragment").d("On ice candidates")
    }

    override fun onDataChannel(p0: DataChannel?) {
        Timber.tag("VoiceChatFragment").d("On Data Channel")
    }

    override fun onIceConnectionReceivingChange(p0: Boolean) {
        Timber.tag("VoiceChatFragment").d("On Ice connection receiving change")
    }

    override fun onIceConnectionChange(p0: PeerConnection.IceConnectionState?) {
        Timber.tag("VoiceChatFragment").d("On ice connection change")
    }

    override fun onIceGatheringChange(p0: PeerConnection.IceGatheringState?) {
        Timber.tag("VoiceChatFragment").d("On ice gathering change")
    }

    override fun onAddStream(p0: MediaStream?) {
        Timber.tag("VoiceChatFragment").d("On Add stream")
    }

    override fun onSignalingChange(p0: PeerConnection.SignalingState?) {
        Timber.tag("VoiceChatFragment").d("On Signaling change")
    }

    override fun onIceCandidatesRemoved(p0: Array<out IceCandidate>?) {
        Timber.tag("VoiceChatFragment").d("On ice candidates removed")
    }

    override fun onRemoveStream(p0: MediaStream?) {
        Timber.tag("VoiceChatFragment").d("On remove stream")
    }

    override fun onRenegotiationNeeded() {
        Timber.tag("VoiceChatFragment").d("On renegotiation needed")
    }

    override fun onAddTrack(p0: RtpReceiver?, p1: Array<out MediaStream>?) {
        Timber.tag("VoiceChatFragment").d("On add track")
    }
}
开放类PeerConnectionObserver:PeerConnection.Observer{
覆盖IceCandidate(p0:ICEScandidate?){
Timber.tag(“VoiceChatFragment”).d(“冰上候选人”)
}
覆盖数据通道(p0:数据通道?){
Timber.tag(“VoiceChatFragment”).d(“在数据通道上”)
}
重写OniconConnectionReceivingChange(p0:布尔值){
Timber.tag(“VoiceChatFragment”).d(“冰上连接接收变更”)
}
重写连接更改(p0:PeerConnection.IceConnectionState?){
Timber.tag(“VoiceChatFragment”).d(“冰上连接变更”)
}
覆盖更改(p0:PeerConnection.IceGatheringState?){
Timber.tag(“VoiceChatFragment”).d(“关于冰收集的变化”)
}
覆盖ADStream(p0:MediaStream?){
Timber.tag(“VoiceChatFragment”).d(“添加流”)
}
覆盖fun onSignalingChange(p0:PeerConnection.SignalingState?){
Timber.tag(“VoiceChatFragment”).d(“关于信号变化”)
}
覆盖已删除的onIceCandidatesRemoved(p0:Array?){
Timber.tag(“VoiceChatFragment”).d(“在冰上移除”)
}
覆盖onRemoveStream(p0:MediaStream?){
Timber.tag(“VoiceChatFragment”).d(“在移除流上”)
}
覆盖重新协商所需的乐趣(){
Timber.tag(“VoiceChatFragment”).d(“需要重新谈判”)
}
覆盖ADDROCK上的乐趣(p0:RTPRECIVER?,p1:Array?){
Timber.tag(“VoiceChatFragment”).d(“在添加轨道上”)
}
}
open class AppSdpObserver : SdpObserver {
    override fun onSetFailure(p0: String?) {
        Timber.tag("VoiceChatFragment").d("On set failure. Reason $p0")
    }

    override fun onSetSuccess() {
        Timber.tag("VoiceChatFragment").d("On set success")
    }

    override fun onCreateSuccess(p0: SessionDescription?) {
        Timber.tag("VoiceChatFragment").d("On create success")
    }

    override fun onCreateFailure(p0: String?) {
        Timber.tag("VoiceChatFragment").d("On create failure. Reason $p0")
    }
}
open class PeerConnectionObserver : PeerConnection.Observer {
    override fun onIceCandidate(p0: IceCandidate?) {
        Timber.tag("VoiceChatFragment").d("On ice candidates")
    }

    override fun onDataChannel(p0: DataChannel?) {
        Timber.tag("VoiceChatFragment").d("On Data Channel")
    }

    override fun onIceConnectionReceivingChange(p0: Boolean) {
        Timber.tag("VoiceChatFragment").d("On Ice connection receiving change")
    }

    override fun onIceConnectionChange(p0: PeerConnection.IceConnectionState?) {
        Timber.tag("VoiceChatFragment").d("On ice connection change")
    }

    override fun onIceGatheringChange(p0: PeerConnection.IceGatheringState?) {
        Timber.tag("VoiceChatFragment").d("On ice gathering change")
    }

    override fun onAddStream(p0: MediaStream?) {
        Timber.tag("VoiceChatFragment").d("On Add stream")
    }

    override fun onSignalingChange(p0: PeerConnection.SignalingState?) {
        Timber.tag("VoiceChatFragment").d("On Signaling change")
    }

    override fun onIceCandidatesRemoved(p0: Array<out IceCandidate>?) {
        Timber.tag("VoiceChatFragment").d("On ice candidates removed")
    }

    override fun onRemoveStream(p0: MediaStream?) {
        Timber.tag("VoiceChatFragment").d("On remove stream")
    }

    override fun onRenegotiationNeeded() {
        Timber.tag("VoiceChatFragment").d("On renegotiation needed")
    }

    override fun onAddTrack(p0: RtpReceiver?, p1: Array<out MediaStream>?) {
        Timber.tag("VoiceChatFragment").d("On add track")
    }
}