Code doesn't even enter the onIceCandiate() while answering the SDP for webRTC in flutter
178
So, I can clearly see that there you haven't set any local description for the remote user who is going to answer this call.
_peerConnection.setLocalDescription(description2);
Hope this might help!
Author by
hamere
Updated on December 22, 2022Comments
-
hamere over 1 year
The code flow doesn't even enter the onIceCandidate function while answering the SDP for webRTC connection. The webRTC is used for Voice calling for VOIP in android and I have also setted up TURN server with viagene website.
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: MyHomePage(title: 'WebRTC lets learn together'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { CollectionReference firebaseInstance = FirebaseFirestore.instance.collection("dmeet"); RTCPeerConnection _peerConnection; MediaStream _localStream; RTCVideoRenderer _remoteRenderer = RTCVideoRenderer(); var docId = TextEditingController(); var l; var document; _createOfferSdp() async { RTCSessionDescription description = await _peerConnection.createOffer({'offerToReceiveAudio': 1}); Map<String, dynamic> session = {"sdp": description.sdp}; document = firebaseInstance.doc(); document.collection("sdp").doc("offersdp").set(session); await _peerConnection.setLocalDescription(description); document.collection("icecandidate").snapshots().listen((result) async { dynamic candidate = new RTCIceCandidate( result['candidate'], result['sdpMid'], result['sdpMlineIndex']); await _peerConnection.addCandidate(candidate); }); print(session); _peerConnection.onIceCandidate = (event) { if (event.candidate != null) { Map<String, dynamic> icecandidate = { "candidate": event.candidate, "sdpMid": event.sdpMid, "sdpMlineIndex": event.sdpMlineIndex }; document.collection("candidate").doc().set(icecandidate); } }; } bool remotesaved = false; _createAnswerSdp() async { _peerConnection.onIceCandidate = (event) { print("Candiate ${event.candidate}"); if (event.candidate != null) { // Map<String, dynamic> icecandidate = { // "candidate": event.candidate, // "sdpMid": event.sdpMid, // "sdpMlineIndex": event.sdpMlineIndex // }; // document.collection("candidate").doc().set(icecandidate); print("Candidate: ${event.candidate}"); } }; firebaseInstance .doc(docId.text) .collection("sdp") .doc("offersdp") .get() .then((value) async { var remoteSession = value.data()["sdp"]; RTCSessionDescription description1 = RTCSessionDescription(remoteSession, "offer"); await _peerConnection .setRemoteDescription(description1) .then((value) async { RTCSessionDescription description2 = await _peerConnection.createAnswer({'offerToReceiveAudio': 1}); Map<String, dynamic> session = {"sdp": description2.sdp}; firebaseInstance .doc(docId.text) .collection("sdp") .doc("answersdp") .set(session); final iceCandidate = await firebaseInstance .doc(docId.text) .collection("candidate") .get(); iceCandidate.docs.forEach((element) async { print("Candidate ${element.data()["candidate"]}"); dynamic candidate = RTCIceCandidate(element.data()['candidate'], element.data()['sdpMid'], element.data()['sdpMlineIndex']); await _peerConnection.addCandidate(candidate); }); }); }); } showAlertDialog(BuildContext context) { // set up the buttons Widget cancelButton = FlatButton( child: Text("Cancel"), onPressed: () {}, ); Widget continueButton = FlatButton( child: Text("Continue"), onPressed: _createAnswerSdp, ); // set up the AlertDialog AlertDialog alert = AlertDialog( title: Text("AlertDialog"), content: TextField( controller: docId, ), actions: [ cancelButton, continueButton, ], ); // show the dialog showDialog( context: context, builder: (BuildContext context) { return alert; }, ); } initRenderer() async { await _remoteRenderer.initialize(); } @override void initState() { _createPeerConnection().then((pc) { _peerConnection = pc; }); initRenderer(); // _localStream.initialize(); super.initState(); } @override void dispose() { _remoteRenderer.dispose(); super.dispose(); } _getUserMedia() async { final Map<String, dynamic> mediaConstraints = { 'audio': true, 'video': false, }; MediaStream stream = await navigator.getUserMedia(mediaConstraints); // _localStream = stream; // _peerConnection.addStream(stream); return stream; } _createPeerConnection() async { Map<String, dynamic> configuration = { "iceServers": [ {"url": "stun:stun.l.google.com:19302"}, { "url": "turn:numb.viagenie.ca", "username": "******@gmail.com", "credential": "*****", } ] }; final Map<String, dynamic> offerSdpConstraints = { "mandatory": { "OfferToReceiveAudio": true, "OfferToReceiveVideo": false, }, "optional": [], }; _localStream = await _getUserMedia(); RTCPeerConnection pc = await createPeerConnection(configuration, offerSdpConstraints); pc.addStream(_localStream); pc.onIceCandidate = (e) { if (e.candidate != null) { l = json.encode({ 'candidate': e.candidate.toString(), 'sdpMid': e.sdpMid.toString(), 'sdpMlineIndex': e.sdpMlineIndex, }); print("Her $l"); } }; pc.onAddStream = (stream) { print('addStream: ' + stream.id); _remoteRenderer.srcObject = stream; }; return pc; } @override Widget build(BuildContext context) { return Scaffold( body: Container( child: Center( child: Row( children: [ Flexible(child: RTCVideoView(_remoteRenderer)), ElevatedButton( child: Text("Create"), onPressed: _createOfferSdp, ), ElevatedButton( onPressed: () { showAlertDialog(context); }, child: Text("Join"), ) ], ), ), ), ); } }
The Line that does not even entered is the function _createAnwerSdp() and next line to it! The createAnswerSdp function is used for answering the call while getting the ice candidate.
What may be cause for the issue?