Closed danteCarvalho closed 3 years ago
You need an available turn server.
Well in may case, i need the app to work without internet, and for a turn server i need internet, isn't? I just tryed with the Meshenger app and it works. phone 1 is with: tethering on wifi off mobile data off. phone 2 is with: tethering off wifi on (connected on phone 1) mobile data off. with this config, video and audio works. but with the flutter webrtc it does not work.
Ok my code basicaly is: send and receive offer, send and receive answer, start rtc and the local server
Map<String, dynamic> configuration = {
"iceServers": [
// {"url": "stun:stun.l.google.com:19302"},
// {"url": "stun:stun1.l.google.com:19302"},
// {"url": "stun:stun2.l.google.com:19302"},
// {"url": "stun:stun3.l.google.com:19302"},
// {"url": "stun:stun4.l.google.com:19302"},
],
"iceTransportPolicy": "all",
"bundlePolicy": "max-bundle",
// "rtcpMuxPolicy": "negotiate",
"iceCandidatePoolSize": 50,
// "tcpCandidatePolicy": "disabled",
"candidateNetworkPolicy": "all",
// "keyType": "RSA",
};
final Map<String, dynamic> constraintsTrue = {
'mandatory': {
'OfferToReceiveAudio': false,
'OfferToReceiveVideo': true,
},
'optional': [
// {'DtlsSrtpKeyAgreement': false}
],
};
final Map<String, dynamic> mediaConstraints = {
'audio': false,
'video': {
'mandatory': {
'minWidth': '640',
// Provide your own width, height and frame rate here
'minHeight': '480',
'minFrameRate': '30',
},
'facingMode': 'user',
'optional': [],
}
};
startRtc() async {
_peerConnection = await createPeerConnection(configuration, constraintsTrue);
_peerConnection.onSignalingState = _onSignalingState;
_peerConnection.onIceGatheringState = _onIceGatheringState;
_peerConnection.onIceConnectionState = _onIceConnectionState;
_peerConnection.onAddStream = _onAddStream;
_peerConnection.onRemoveStream = _onRemoveStream;
_peerConnection.onIceCandidate = _onCandidate;
_peerConnection.onRenegotiationNeeded = _onRenegotiationNeeded;
localStream = await navigator.getDisplayMedia(mediaConstraints);
await _peerConnection.addStream(localStream);
RTCSessionDescription rtcSessionDescription = await _peerConnection.createOffer(constraintsTrue);
await _peerConnection.setLocalDescription(rtcSessionDescription);
sdp = rtcSessionDescription.sdp;
}
sendOffer() async {
if (sdp == null) {
await startRtc();
}
String ips = await platform.invokeMethod('getIps');
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
var split = ips.split(" ");
var repo = Modular.get<EnviarOfertaRepository>();
for (var ip in split) {
if (ip.contains(".")) {
var ipRange = ip.substring(0, ip.lastIndexOf(".") + 1);
for (int i = 0; i < 255; i++) {
var ip2 = ipRange + i.toString();
if (ip == ip2) {
continue;
}
Map map = Map();
map["sdp"] = sdp;
map["modelo"] = androidInfo.model;
map["ip"] = ip;
map["candidatos"] = candidates;
repo.fetchPost(ip2, map);
}
} else {
Map map = Map();
map["sdp"] = sdp;
map["modelo"] = androidInfo.model;
map["ip"] = ip;
map["candidatos"] = candidates;
repo.fetchPost("[$ip]", map);
}
}
}
receiveOffer(request) async {
String s = await utf8.decoder.bind(request).join();
Map map = json.decode(s);
if (!lista.contains(map)) {
lista.add(map);
}
}
sendAnswer(index) async {
await close1();
print('WWWWWW RECEIVING VIDEO');
var item = lista[index];
_peerConnection = await createPeerConnection(configuration, constraintsTrue);
_peerConnection.onSignalingState = _onSignalingState;
_peerConnection.onIceGatheringState = _onIceGatheringState;
_peerConnection.onIceConnectionState = _onIceConnectionState;
_peerConnection.onAddStream = _onAddStream;
_peerConnection.onRemoveStream = _onRemoveStream;
_peerConnection.onIceCandidate = _onCandidate;
_peerConnection.onRenegotiationNeeded = _onRenegotiationNeeded;
var rtcSessionDescription = new RTCSessionDescription(item['sdp'], "offer");
await _peerConnection.setRemoteDescription(rtcSessionDescription);
List candidatos = item["candidatos"];
for (var candidato in candidatos) {
RTCIceCandidate candidate = new RTCIceCandidate(candidato['candidate'], candidato['sdpMid'], candidato['sdpMLineIndex']);
await _peerConnection.addCandidate(candidate);
}
RTCSessionDescription rtcSessionDescription2 = await _peerConnection.createAnswer(constraintsTrue);
await _peerConnection.setLocalDescription(rtcSessionDescription2);
var remoteIp = item["ip"];
Future.delayed(Duration(seconds: 3), () async {
Map map = Map();
map["sdp"] = rtcSessionDescription2.sdp;
map["candidatos"] = candidatos;
var repo = Modular.get<EnviarRespostaRepository>();
repo.fetchPost(remoteIp, map);
});
}
receiveAnswer(request) async {
print('WWWWWW SENDING VIDEO');
String s = await utf8.decoder.bind(request).join();
Map map = json.decode(s);
var rtcSessionDescription = new RTCSessionDescription(map["sdp"], "answer");
await _peerConnection.setRemoteDescription(rtcSessionDescription);
List candidatos = map["candidatos"];
for (var candidato in candidatos) {
RTCIceCandidate candidate = new RTCIceCandidate(candidato['candidate'], candidato['sdpMid'], candidato['sdpMLineIndex']);
await _peerConnection.addCandidate(candidate);
}
cameras = await availableCameras();
cameraController = CameraController(cameras[0], ResolutionPreset.medium);
await cameraController.initialize().then((_) {});
showCamera = true;
}
await for (HttpRequest request in server) {
try {
print("WWWWWW " + request.uri.path);
if (request.method == "POST") {
request.response.headers.add("Access-Control-Allow-Origin", "*");
if (request.uri.path == "/webserver/receberOferta") {
await receiveOffer(request);
} else if (request.uri.path == "/webserver/receberResposta") {
await receiveAnswer(request);
}
}
} catch (e) {
print(e);
Map obj = Map();
obj["mensagem"] = e.toString();
String myJson = json.encode(obj);
request.response.write(myJson);
} finally {
await request.response.close();
}
}
what is weird is that the _onAddStream method woks, it receives the stream, but its like there is no data on the stream when is on tethering, but works fine on wifi, and i see no error/exception.
working exemple here https://bitbucket.org/dantecarvalho/testewebrtc/src/master/
A key point, you need to ensure that the candidate packet is the timing of receiving and sending. PeerA’s candidate sometimes arrives earlier than its own offer sdp, so you may need to store the candidate in a queue in PeerB first, wait until setRemoteDescription is completed, and then addCandidate, so as to ensure connectivity.
Ok i changed the code, now on PeerB i set remote and local description
var rtcSessionDescription = new RTCSessionDescription(item['sdp'], "offer");
await _peerConnection.setRemoteDescription(rtcSessionDescription);
RTCSessionDescription rtcSessionDescription2 = await _peerConnection.createAnswer(constraintsTrue);
await _peerConnection.setLocalDescription(rtcSessionDescription2);
then wait for the gathering state to be completed
_peerConnection.iceGatheringState == RTCIceGatheringState.RTCIceGatheringStateComplete
then i add the candidates received from the GatheringState and the cadidates received from PeerA, and start rendering the stream received on the onAddStream.
and finaly i send the answer to PeerA.
But again it only works on the wifi, on the tethering nothing shows.
Could you give it a try with this code? https://bitbucket.org/dantecarvalho/testewebrtc/src/master/
I noticed that in one peer the ice connection and the peer connection don't change from checking and connecting
I/flutter (15029): WWWWW Ice Connection I/flutter (15029): RTCIceConnectionState.RTCIceConnectionStateChecking I/flutter (15029): WWWWW Peer connection I/flutter (15029): RTCPeerConnectionState.RTCPeerConnectionStateConnecting I/flutter (15029): WWWWW Ice Connection I/flutter (15029): RTCIceConnectionState.RTCIceConnectionStateChecking I/flutter (15029): WWWWW Peer connection I/flutter (15029): RTCPeerConnectionState.RTCPeerConnectionStateConnecting
and on the other peer
I/flutter (17595): WWWWW Ice Connection I/flutter (17595): RTCIceConnectionState.RTCIceConnectionStateChecking I/flutter (17595): WWWWW Peer connection I/flutter (17595): null I/flutter (17595): WWWWW Ice Connection I/flutter (17595): RTCIceConnectionState.RTCIceConnectionStateChecking I/flutter (17595): WWWWW Peer connection I/flutter (17595): null
Yeess i finally solve it. After alot of digging i saw this post https://www.talkend.net/post/52763.html, it says that you need to turn off the network monitor when the PeerConnectionFactory is created because the monitor throws this error:
android_network_monitor.cc Get an unknown type for the interface
I gues this is because the interface names for tethering on android phones varys depending on phone, model, brand etc..
So after changing the factory initialization like this, it worked:
PeerConnectionFactory.Builder builder = PeerConnectionFactory.builder();
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
options.disableNetworkMonitor = true;
builder.setOptions(options);
mFactory = builder.setVideoEncoderFactory(new DefaultVideoEncoderFactory(eglContext, false, true))
.setVideoDecoderFactory(new DefaultVideoDecoderFactory(eglContext))
.setAudioDeviceModule(audioDeviceModule)
.createPeerConnectionFactory();
You should make an option to turn off the network monitor for the people that don't need it.
Yeess i finally solve it. After alot of digging i saw this post https://www.talkend.net/post/52763.html, it says that you need to turn off the network monitor when the PeerConnectionFactory is created because the monitor throws this error:
android_network_monitor.cc Get an unknown type for the interface
I gues this is because the interface names for tethering on android phones varys depending on phone, model, brand etc..
So after changing the factory initialization like this, it worked:
PeerConnectionFactory.Builder builder = PeerConnectionFactory.builder(); PeerConnectionFactory.Options options = new PeerConnectionFactory.Options(); options.disableNetworkMonitor = true; builder.setOptions(options); mFactory = builder.setVideoEncoderFactory(new DefaultVideoEncoderFactory(eglContext, false, true)) .setVideoDecoderFactory(new DefaultVideoDecoderFactory(eglContext)) .setAudioDeviceModule(audioDeviceModule) .createPeerConnectionFactory();
You should make an option to turn off the network monitor for the people that don't need it.
My issue is similar to yours. In my case, it works only with hotspot/tethering on android and ios. It's not working on WIFI and Mobile data.
Can you guide me to configure the above solution and where?
For now you need to have a copy of the flutter-webrtc package on your computer and change the file .../flutter_webrtc-0.5.7/android/src/main/java/com/cloudwebrtc/webrtc/MethodCallHandlerImpl.java on the ensureInitialized method where the factory is created. Thats it, you don't need to change anything on your code. Even VPN works with this change.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
@cloudwebrtc can you make an option to configure this?
options.disableNetworkMonitor = true;
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This is still an issue--the patch mentioned does work, but I have to maintain my own fork. Is there any way to get this in a release?
but “options.disableNetworkMonitor = true;” i test not work
I am trying to test somethings with webrtc, and using the https://github.com/meshenger-app/meshenger-android app the connection works just fine with the phone therering. But when i try with the https://pub.dev/packages/flutter_webrtc it only works with wifi. Is there a why to this?