I am new to WebRTC native framework.
I was able to get the WebRTC source and run the demo Android application based on http://andrii.sergiienko.me/?go=all/building-webrtc-demo-for-android/enter link description here.
I was able to send/receive Audio and Video between two Android devices on the same local network.
Is there any way to send a small JSON payload in this peer connection?
I tried looking for it in the source and I only found support to send Video and Audio.
Thank you.
Your are looking for WebRTC DataChannels.
WebRTC's RTCDataChannel API is used to transfer data directly from one peer to another. This is great for sending data between two browsers(Peers) for activities like communication, gaming, or file transfer and slew of other functionalities.
It is an Alternative For WebSockets:
This is a great alternative to WebSockets because no central server is involved and transmission is usually faster and there is no bottleneck. You can of course mitigate the failover of P2P transfer by having a hooks which activates Websockets based communication if P2P data-channel communication fails.
Code for Reference:
The events defined are called when you wish to send a message of when a message is received (including error handling). This code should be running in both the browsers. Instead of sending "Hello World" you just need to send your JSON String.
var peerConnection = new RTCPeerConnection();
// Establish your peer connection using your signaling channel here
var dataChannel =
peerConnection.createDataChannel("myLabel", dataChannelOptions);
dataChannel.onerror = function (error) {
console.log("Data Channel Error:", error);
};
dataChannel.onmessage = function (event) {
console.log("Got Data Channel Message:", event.data);
};
dataChannel.onopen = function () {
dataChannel.send("Hello World!");
};
dataChannel.onclose = function () {
console.log("The Data Channel is Closed");
};
The dataChannel object is created from an already established peer connection. It can be created before or after signaling happens. You then pass in a label to distinguish this channel from others and a set of optional configuration settings:
var dataChannelOptions = {
ordered: false, // do not guarantee order
maxRetransmitTime: 3000, // in milliseconds
};
For more details check out the links provided.
Examples:
Link to official documentation: DataChannels in WebRTC
Link to a file Trasfer example using WebRTC Data Channels.
File Transfer
Link to popular Use Cases for WebRTC Data Channels
Use Cases
Related
In my Android WebRTC client to send DTFM tones I use code like this
val audioSource = peerConnectionFactory.createAudioSource(MediaConstraints())
val localAudioTrack = peerConnectionFactory.createAudioTrack("audio", audioSource)
peerConnection.addTrack(localAudioTrack)
peerConnection?.senders?.firstOrNull()?.let {
it.dtmf()?.insertDtmf(code, 400, 50)
}
But it seems tone does not reach a peer, and there is erro message in logcat
dtmf_sender.cc E (line 126): InsertDtmf is called on DtmfSender that can't send DTMF.
No matter what device I use.
Why could it happen?
There are multiple reasons why this could happen, one of them being that the other party in the WebRTC connection does not support the RTP telephone-event
Also, check this example: https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Using_DTMF
(haven't tried it myself though)
Pay attention to this:
"Note, however, that although it's possible to send DTMF using WebRTC, there is currently no way to detect or receive incoming DTMF. WebRTC currently ignores these payloads; this is because WebRTC's DTMF support is primarily intended for use with legacy telephone services"
I have found, problem is that peers are not connected via RTP. I mean WebRTC did not found yet suitable route, basing on ICE candidates gathered, to pass audio traffic.
As only route is constructed, traffic goes on, and sender comes ready to send DTMF tones.
To be ensured that peers are ready to trancieve media, you may look on connection state in PeerConnection.Observer.onIceConnectionChange(), and get sender when state comes to "CONNECTED".
I am implementing a webRTC android application, and the servers that i am communicating with are a signaling server(via websockets) and a kurento media server.
Time sequence is:
clients subscribe to the server
every client sent sdpOffer
every client sent all the iceCandidate that will be created
signaling server send the iceCandidate to every client
signaling server send to the clients the sdpAnswers which originate from kurento media server
My mobile clients subscribe to the server and they send theirs sdpOffers.
After ice trickle the signaling server sending back the sdpAnswers from kurento media server.
So, i am getting the startCommunication messages and the remote description is set successfully with the sdpAnswers from kurento media server.
I have check all my sdp and ice packages, they are all as expected, and all webRTC related callbacks are successful.
After setting the remoteDescription in peerConnection,
the onAddStream() is invoked and i am getting the videoTrack.But the video is not rendering..
my onAddStream:
override fun onAddStream(p0: MediaStream?) {
super.onAddStream(p0)
p0?.videoTracks?.get(0)?.addSink(remote_view)
Log.d(TAG, "on add stream" + p0?.videoTracks?.size )
Log.d(TAG,App.rtcClient.peerConnection?.iceConnectionState().toString())
Log.d(TAG,App.rtcClient.peerConnection?.iceGatheringState().toString())
}
init of the remote view:
fun initSurfaceView(view: SurfaceViewRenderer) = view.run {
setMirror(true)
setEnableHardwareScaler(true)
init(rootEglBase.eglBaseContext, null)
}
....
App.rtcClient.initSurfaceView(remote_view)
xml of the remote view:
<org.webrtc.SurfaceViewRenderer
android:id="#+id/remote_view"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/local_view" />
I am not getting any errors and my local stream is rendering perfectly.
So, i am debugging the app without knowing where to go next, because is not clear where this problem comes from.
This exact question exists here but there is no answers and it is 5 y.o
if you need any additional info please comment.
Update: Exact the same behavior exists in the iOS version too - no video rendering.
I am trying make an application that will allow a registered client to make an audio call to another registered client using Wi-Fi(It doesn't require internet).
I was able to successfully register and make call using SIP.
After the call is picked up, I don't know how to handle the RTP stream and connect it with the microphone and speaker of the phone(Android and IOS) to perform normal calling functionality.
I am using Xamarin and SIP Sorcery library. I am new to Xamarin and mobile application development.
Below is a part of code to explain myself a little better:
async Task Call()
{
Console.WriteLine("Start of Calling section");
rtpSession = new RTPMediaSession((int)SDPMediaFormatsEnum.PCMU, AddressFamily.InterNetwork);
// May be somthing like this to connect audio devices to RTP session.
//get microphone
//get speaker
//ConnectAudioDevicesToRtp(rtpSession, microphone, speaker);
// Place the call and wait for the result.
bool callResult = await userAgent.Call(DESTINATION, ssid, userName, registerPassword, domainHost, rtpSession);
if (callResult)
{
Console.WriteLine("Call attempt successful. Start talking");
//I am reaching to this point and need help with how to move forward from here to support audio calling functionality for both Android and IOS
}
else
{
Console.WriteLine("Call attempt failed.");
}
}
Any help or direction would be appreciated. Thank you.
I looked at the documentation from SIP Sorcery, there I found only an example for windows (https://sipsorcery.github.io/sipsorcery/articles/sipuseragent.html), but not for ios or android.
Here is the description from SIP Sorcery for cross platform (https://sipsorcery.github.io/sipsorcery/). I think you need the SIPSorceryMedia.FFmpeg library
I have a really huge place in which what I need is that people can chat with each other. I would place WiFi router to cover the whole place but, due to the high amount of people, I can't provide an internet connection through that network. Which technology should I use? I've been reading about AllJoyn but I don't know if that would help me. Also, because of the amount of people (over 75,000) I can't setup a server to handle the service, per connection, 1 devices will have to be the host and the other one will have to be the client. Thanks
If you want to create your own application you could use something like Signalr and Xamarin using their SignalR component.
Taken from the Quick Usage on the component page:
// Connect to the server
var hubConnection = new HubConnection("http://server.com/");
// Create a proxy to the 'ChatHub' SignalR Hub
var chatHubProxy = hubConnection.CreateHubProxy("ChatHub");
// Wire up a handler for the 'UpdateChatMessage' for the server
// to be called on our client
chatHubProxy.On<string>("UpdateChatMessage", message =>
text.Text += string.Format("Received Msg: {0}\r\n", message));
// Start the connection
await hubConnection.Start();
// Invoke the 'UpdateNick' method on the server
await chatHubProxy.Invoke("UpdateNick", "JohnDoe");
Alternatively there are applications out there that likely do what you want already. For example http://beebeep.sourceforge.net/
Lets say there are two android devices and a webpage.
On each of those devices there is a button being clicked and the webpage shows the accumulated clicks.
What makes this possible?
Are the android devices sending that data to a sql database and that counter is reading what currently is in that database?
Or can the device really send the information into the page?
The device can communicate data to the server or to the client side code. You can then have to decide what to do with the data. If you send it to the client side code then it would only update on one device, whereas sending it to the server would allow one click counter across every device.
Changing the page on the server side would add caching problems. So you probably want a data file instead, just a json or something that the server overwrites every time it receives another click.
This isn't very fast though and causes synchronisation issues between the users. For starters for a standard html page the client code is in charge of the calls to the server, so we would have to check the server periodically to see if the value has changed (say every 5 seconds).
A faster alternative would be to use a web socket. The client would keep a connection open to the server and listen for updates from the server, removing the need for our periodic check. Additionally the socket can be used to send clicks to the server and the server can keep the value in its memory removing the need for file writes.
Node.js can be downloaded from http://nodejs.org and this is the plug in I use for web sockets https://github.com/Worlize/WebSocket-Node.
So here is some server side code for a simple web socket server that parrots messages from 1 user to all users, including the user who sent it.
var connections = [];
var WebSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
// process HTTP request. Since we're writing just WebSockets server
// we don't have to implement anything.
});
server.listen(1337, function() { });
// create the server
wsServer = new WebSocketServer({
httpServer: server
});
// WebSocket server
wsServer.on('request', function(request) {
//got a new user requesting a connection, so lets accept and store them
var connection = request.accept(null, request.origin);
connections.push(connection);
connection.on('message', function(message) { //inbound message
if (message.type === 'utf8') {
// process WebSocket message
send(message.utf8Data); //bounce to everyone else
console.log(message);
}
});
});
setInterval(function(){console.log(connections.length +" :users");},5000);
//every 5 seconds, tell us how many users we have
function send(message){
var i = connections.length;
while(i--)
connections[i].send(message);
//send the message to all users
}
Example client side
<html><head><script>
var connection, connIsActive = false;
// if user is running mozilla then use it's built-in WebSocket
window.WebSocket = window.WebSocket || window.MozWebSocket;
connection = new WebSocket('ws://127.0.0.1:1337');
connection.onopen = function () {
// connection is opened and ready to use
connIsActive = true;
console.log('Connection loaded');
};
connection.onerror = function (error) {
// an error occurred when sending/receiving data
connIsActive = false
console.log('error');
};
connection.onmessage = function (message) {
// handle incoming message
console.log(message.data);
};
function send(message){
if(connIsActive)connection.send(message);
}
</script></head></html>
Save the first snippet as "myserver.js" (or similar) and start it up in node via command line. Save the second snippet as a "client.html" and open it on 2 devices, or just 2 browser instances. Theres no interface on the client but you can send and receive messages from the debug console using send("message string")
Provided you can wrap your head around my snippets, modifying it to work like your example should prove fairly easy!
To achieve what you are trying to do, you need to learn socket programming for android.
In order to use two device(clients) you also need to learn port forwarding for servers.
To begin try this tutorial.