Перво-наперво, я мало что знаю о WebRTC для Android, но я думаю, что он будет очень похож на веб-API. Я использовал стандартные js в своем потоке ниже.
Относительно триггера onicecandidate:
вызывается обработчик onicecandidate, , когда вы задаете свое локальное описание , см. MDN onicecandidateevent . Вам нужно установить локальное описание, чтобы начать процесс сбора льда. Одна из причин заключается в том, что собранные ледовые кандидаты будут добавлены в ваше локальное описание, и если у вас нет локального описания, чтобы добавить их, оно не будет работать.
Относительно вашего потока (возможно, для проверки):
Что касается процесса обработки предложения-ответа-обмена, попробуйте сделать это следующим образом (возьмите A и B в качестве одноранговых узлов с отдельным RTCPeerConnection-Объекты pcA и pcB), проверьте, отличается ли ваш поток где-либо:
- Сначала вы должны настроить обработчик для входящих ледовых кандидатов на A и B, например
signaller.on('ice', candidate => pc.addIceCandidate(candidate))
- ЗатемВы должны зарегистрировать свои обработчики треков для A и B, например
pcA.ontrack = track => ... (put it as src of your video or whatever)
- , добавить MediaStreamTracks к соединениям
pcA.addTrack(aTrack)
(начиная со стороны A ...)
A генерирует предложение по телефону
offer = await pcA.createOffer()
A устанавливает сгенерированное предложение в качестве локального описания
await pcA.setLocalDescription(offer)
A отправляет сгенерированное предложение по каналу сигнализации
signaller.sendTo('B','offer', offer)
, теперь вашначинается процесс сбора льда A получает сгенерированных кандидатов обработчиком
onicecandidate
.
pcA.onicecandidate = e => signaller.sendTo('B','ice', e.candidate)
(Теперь мы переходим к взгляду B на вещи)
B получает предложение и устанавливает его
signaller.on('offer', async offer => { await pcB.setRemoteDescription(offer); // and the following steps 8 to 12 follow here })
B создает sdp-ответ
answer = await pcB.createAnswer()
B устанавливает ответ как локальное описание
await pcB.setLocalDescription(answer)
СейчасПроцесс сбора льда B начинается параллельно и должен обрабатываться, как в 7. B отправляет ответ A
signaller.sendTo('A','answer', answer)
(Назад к A)
A получает ответ
signaller.on('answer', async answer => await pcA.setRemoteDescription(answer); });
Теперь вызов должен быть завершен, обмен ледяными кандидатами и сигнализация состояния льда должны быть
stable
или
connected
Если это работает, посмотрите на обработку бликов, это хороший источник .