簡體   English   中英

WebRTC onicecandidate 不會在 chrome for android 上觸發,但適用於所有其他瀏覽器,包括 firefox for android

[英]WebRTC onicecandidate is not triggered on chrome for android but works on all other browsers including firefox for android

這是代碼。

sendChannel = localConnection.createDataChannel("sendChannel");
sendChannel.onopen = handleSendChannelStatusChange;
sendChannel.onclose = handleSendChannelStatusChange;

localConnection.ondatachannel = receiveChannelCallback;
localConnection.onicecandidate = e => {
    console.log('candidates found');
    e.candidate && offerCandidates.add(e.candidate.toJSON());
};



var offerDescription = await localConnection.createOffer();
await localConnection.setLocalDescription(offerDescription);

我已經確認它適用於所有桌面瀏覽器和 android 上的 firefox,但是 onicecandidate 從來沒有在 chrome 上為 android 或本機 webview 調用。

我也更新了 chrome、webview 和 android 本身,問題仍然存在。

編輯:我在另一部運行 chrome 版本 84.0.4147.89 的手機上試了一下,效果很好。 有問題的版本是 94.0.4606.85。

我將 chrome 降級到 87.0.4280.141 版本,現在它正在工作,但遺憾的是降級 webview 沒有幫助,這是最終用例。

我的理論是,這是新版本的錯誤或安全問題。 無論如何,這里是完整的代碼,只是為了確保。

import './firebase/firebase.js';


const firebaseConfig = {
    apiKey: "",
    authDomain: "",
    projectId: "",
    storageBucket: "",
    messagingSenderId: "",
    appId: "",
    measurementId: ""
};


if (!firebase.apps.length) {
    firebase.initializeApp(firebaseConfig);
}

var connectButton = null;
var disconnectButton = null;
var sendButton = null;
var messageInputBox = null;
var receiveBox = null;

const servers = {
    iceServers: [
        {
            urls: ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302'],
        },
    ],
    iceCandidatePoolSize: 10,
};
const localConnection = new RTCPeerConnection(servers);
var calldoc;
var offerCandidates;
var answerCandidates;
var sendChannel = null;       // RTCDataChannel for the local (sender)
var receiveChannel = null;    // RTCDataChannel for the remote (receiver)
var answerInput = null;
var answerButton = null;
var connected = false;
var id = null;
var dataConstraint;

function startup() {
    connectButton = document.getElementById('connectButton');
    disconnectButton = document.getElementById('disconnectButton');
    sendButton = document.getElementById('sendButton');
    messageInputBox = document.getElementById('message');
    receiveBox = document.getElementById('receivebox');
    answerInput = document.getElementById('answerID');
    answerButton = document.getElementById('answerButton');
    // Set event listeners for user interface widgets
    answerButton.addEventListener('click', listenForConnection, false);
    connectButton.addEventListener('click', connectPeers, false);
    disconnectButton.addEventListener('click', disconnectPeers, false);
    sendButton.addEventListener('click', sendMessage, false);
}

function onicecandidate (e) {
    console.log('candidates found');
    e.candidate && offerCandidates.add(e.candidate.toJSON());
};

export async function connectPeers() {
    // Create the local connection and its event listeners
    
    calldoc = firebase.firestore().collection('calls').doc();
    
    // Create the data channel and establish its event listeners
    dataConstraint = null;
    sendChannel = localConnection.createDataChannel("sendChannel", dataConstraint);
    sendChannel.onopen = handleSendChannelStatusChange;
    sendChannel.onclose = handleSendChannelStatusChange;
    localConnection.ondatachannel = receiveChannelCallback;
    localConnection.onicecandidate = onicecandidate;
    
    id = calldoc.id;
    offerCandidates = calldoc.collection('offerCandidates');
    answerCandidates = calldoc.collection('answerCandidates');
   
    var offerDescription = await localConnection.createOffer();
    await localConnection.setLocalDescription(offerDescription);

    
    
    const offer = {
        sdp: offerDescription.sdp,
        type: offerDescription.type,
    };
    

    await calldoc.set({offer});

    calldoc.onSnapshot((snapshot) => {
        const data = snapshot.data();
        if (data !== null) {
            if (!localConnection.currentRemoteDescription && data.answer) {
                const answerDescription = new RTCSessionDescription(data.answer);
                localConnection.setRemoteDescription(answerDescription);

            }
        }
    });

    answerCandidates.onSnapshot(snapshot => {
        snapshot.docChanges().forEach((change) => {
            if (change.type === 'added') {
                const candidate = new RTCIceCandidate(change.doc.data());
                localConnection.addIceCandidate(candidate);
                console.log("found answer");
                connected = true;
            }
        });
    });

}

async function listenForConnection() {

    calldoc = firebase.firestore().collection('calls').doc(answerInput.value);
    answerCandidates = calldoc.collection('answerCandidates');

    localConnection.onicecandidate = event => {
        event.candidate && answerCandidates.add(event.candidate.toJSON());
    };
    // Create the data channel and establish its event listeners
    sendChannel = localConnection.createDataChannel("receiveChannel");
    sendChannel.onopen = handleSendChannelStatusChange;
    sendChannel.onclose = handleSendChannelStatusChange;

    localConnection.ondatachannel = receiveChannelCallback;
    const cdata = (await calldoc.get()).data();
    const offerDescription = cdata.offer;
    await localConnection.setRemoteDescription(new 
          RTCSessionDescription(offerDescription));

    const answerDescription = await localConnection.createAnswer();
    await localConnection.setLocalDescription(answerDescription);

    const answer = {
        type: answerDescription.type,
        sdp: answerDescription.sdp,
    };

    await calldoc.update({ answer });

    offerCandidates.onSnapshot((snapshot) => {
        snapshot.docChanges().forEach((change) => {
            console.log(change)
            if (change.type === 'added') {
                let data = change.doc.data();
                localConnection.addIceCandidate(new RTCIceCandidate(data));
            }
        });
    });

}

// Handle errors attempting to create a description;

function handleCreateDescriptionError(error) {
    console.log("Unable to create an offer: " + error.toString());
}

// Handle successful addition of the ICE candidate
// on the "local" end of the connection.

function handleLocalAddCandidateSuccess() {
    connectButton.disabled = true;
}

// Handle successful addition of the ICE candidate
// on the "remote" end of the connection.

function handleRemoteAddCandidateSuccess() {
    disconnectButton.disabled = false;
}

// Handle an error that occurs during addition of ICE candidate.

function handleAddCandidateError() {
    console.log("Oh noes! addICECandidate failed!");
}

// Handles clicks on the "Send" button by transmitting


export function sendMessage() {
    if (connected === false) {
        return
    }
    var message = messageInputBox.value;
    sendChannel.send(message);

    

    messageInputBox.value = "";
    messageInputBox.focus();
}

// Handle status changes on the local end of the data


function handleSendChannelStatusChange(event) {
    console.log('on open fired???');
    if (sendChannel) {
        var state = sendChannel.readyState;

        if (state === "open") {
            messageInputBox.disabled = false;
            messageInputBox.focus();
            sendButton.disabled = false;
            disconnectButton.disabled = false;
            connectButton.disabled = true;
        } else {
            messageInputBox.disabled = true;
            sendButton.disabled = true;
            connectButton.disabled = false;
            disconnectButton.disabled = true;
        }
    }
}

// Called when the connection opens and the data
// channel is ready to be connected to the remote.

function receiveChannelCallback(event) {
    receiveChannel = event.channel;
    receiveChannel.onmessage = handleReceiveMessage;
    receiveChannel.onopen = handleReceiveChannelStatusChange;
    receiveChannel.onclose = handleReceiveChannelStatusChange;
}

// Handle onmessage events for the receiving channel.
// These are the data messages sent by the sending channel.

function handleReceiveMessage(event) {
    var el = document.createElement("p");
    var txtNode = document.createTextNode(event.data);

    el.appendChild(txtNode);
    receiveBox.appendChild(el);
}

// Handle status changes on the receiver's channel.

function handleReceiveChannelStatusChange(event) {
    if (receiveChannel) {
        console.log("Receive channel's status has changed to " +
            receiveChannel.readyState);
    }

    // Here you would do stuff that needs to be done
    // when the channel's status changes.
}

/

function disconnectPeers() {

    // Close the RTCDataChannels if they're open.

    sendChannel.close();
    receiveChannel.close();

    // Close the RTCPeerConnections

    localConnection.close();
    remoteConnection.close();

    sendChannel = null;
    receiveChannel = null;
    localConnection = null;
    remoteConnection = null;

    // Update user interface elements

    connectButton.disabled = false;
    disconnectButton.disabled = true;
    sendButton.disabled = true;

    messageInputBox.value = "";
    messageInputBox.disabled = true;
}



window.addEventListener('load', startup, false);

很長一段時間后,我發現答案是新 chrome 中的一個錯誤,解決方案是為 Android 10 而不是 11 構建應用程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM