In this tutorial, you will learn how to set up text chat for a conference.
We will use DataChannel for sending and receiving text messages. DataChannel supports the transfer of binary or text data. We can use it to transfer any sort of data outside of the typical audio and video data. Adding DataChannel capability is straightforward. We simply create the DataChannel, wrap it in a DataStream, and then provide that stream to the connection object in the same way as we did for an AudioStream or a VideoStream.
Important
Do not run the app until you have completed all of the instructions in this tutorial. Text chat cannot work until the text channel is declared on both the upstream and downstream sides of the SFU connection.
Prerequisites
This tutorial requires the SFU connection app or any apps you have built earlier on top of it.
Define Sender and Receiver Behaviour
Set up functions for sending and receiving that will ensure messages display both locally and remotely. The sendDataString method is used to send text messages. To receive messages, access the text Channel's DataString attribute from dataChannelReceiveArgs.
Copy the following code into the HelloWorldLogic class:
private DataChannel _TextChannel;
public void SendMessage(string msg)
{
var chatMsg = $"{Client.Id}: {msg}";
DisplayMessage(chatMsg);
_TextChannel.SendDataString(chatMsg);
}
private void OnTextReceive(DataChannelReceiveArgs dataChannelReceiveArgs)
{
var chatMsg = dataChannelReceiveArgs.DataString;
DisplayMessage(chatMsg);
}
// Data channel for sending text messages.
private DataChannel textChannel;
private final String textChannelId = "text-channel";
private MessageAction onMessage;
public interface MessageAction {
void displayMessage(String message);
}
public void setOnMessage(MessageAction action) {
onMessage = action;
}
public void sendMessage(String message) {
if (textChannel != null) {
String chatMessage = client.getId() + ": " + message + "\n";
onMessage.displayMessage(chatMessage);
textChannel.sendDataString(chatMessage);
}
}
var _textChannel: FMLiveSwitchDataChannel?
var _textChannelId: String = "text-channel"
var _displayMessage: ((String) -> Void)? = nil
func setDisplayMessage(action: @escaping (String) -> Void) {
self._displayMessage = action
}
func sendMessage(message: String) {
let chatMessage = "\(String(describing: _client!.id()!)): \(message)"
self._displayMessage!(chatMessage)
self._textChannel?.sendDataString(chatMessage)
}
private textChannel: fm.liveswitch.DataChannel;
public sendMessage(msg: string): void {
// Prepend user ID to the message.
const chatMsg = `${this.client.getUserId()}: ${msg}`;
// Display the message locally.
this.displayMessage(chatMsg);
// Send the message through the data channel.
this.textChannel.sendDataString(chatMsg);
}
private onTextReceive(dataChannelReceiveArgs: fm.liveswitch.DataChannelReceiveArgs): void {
this.displayMessage(dataChannelReceiveArgs.getDataString());
}
Create Text Data Channel Upstream
In the upstream connection, create a DataChannel to send text messages and wrap it in a DataStream.
Paste the following code into the beginning of the openSfuUpstreamConnection function in the HelloWorldLogic class.
// Create data channel and stream
var dataChannelText = new DataChannel("text-channel");
var dataStream = new DataStream(dataChannelText);
if (_TextChannel == null)
{
_TextChannel = dataChannelText;
}
// Create data channel.
DataChannel dataChannelText = new DataChannel(textChannelId);
if (textChannel == null) {
textChannel = dataChannelText;
}
// Create a data stream with the data channel.
DataStream dataStream = new DataStream(dataChannelText);
let dataChannelText = FMLiveSwitchDataChannel(label: _textChannelId)
let dataStream = FMLiveSwitchDataStream(channel: dataChannelText)
if (_textChannel == nil) {
_textChannel = dataChannelText
}
// Create data channel and stream.
const dataChannelText = new fm.liveswitch.DataChannel("text-channel");
const dataStream = new fm.liveswitch.DataStream(dataChannelText);
if (this.textChannel == null) {
this.textChannel = dataChannelText;
}
Then, add the DataStream to the upstream connection by providing the DataStream as an additional parameter to the CreateSfuUpstreamConnection method.
In the openSfuUpstreamConnection function, update the CreateSfuUpstreamConnection method to add dataStream as an additional parameter.
// Create a SFU upstream connection with local audio and video and data stream.
SfuUpstreamConnection connection = channel.createSfuUpstreamConnection(audioStream, videoStream, dataStream);
// Create a SFU upstream connection with local audio and video and data stream.
const connection:fm.liveswitch.SfuUpstreamConnection = this.channel.createSfuUpstreamConnection(audioStream, videoStream, dataStream);
Create Text Data Channel Downstream
In the downstream connection, create a DataChannel and use OnReceive to handle receiving messages event, and wrap the DataChannel in a DataStream.
Paste the following code into the beginning of the openSfuDownstreamConnection function in the HelloWorldLogic class.
// Create data channel and set onReceive
var dataChannelText = new DataChannel("text-channel");
dataChannelText.OnReceive = OnTextReceive;
// Create data stream
var dataStream = new DataStream(dataChannelText);
// Create data channel and set onReceive.
DataChannel dataChannelText = new DataChannel(textChannelId);
dataChannelText.setOnReceive(result -> {
onMessage.displayMessage(result.getDataString());
});
// Create data stream with the data channel.
DataStream dataStream = new DataStream(dataChannelText);
let dataChannelText = FMLiveSwitchDataChannel(label: _textChannelId)
dataChannelText?.setOnReceive(FMLiveSwitchAction1{dataChannelReceiveArgs -> Void in
let args = dataChannelReceiveArgs as! FMLiveSwitchDataChannelReceiveArgs
if (args.dataString() != nil) {
self._displayMessage!(args.dataString())
}
})
let dataStream = FMLiveSwitchDataStream(channel: dataChannelText)
// Create data channel and set onReceive.
const dataChannelText = new fm.liveswitch.DataChannel("text-channel");
dataChannelText.setOnReceive((e) => this.onTextReceive(e));
// Create data stream with the data channel.
const dataStream = new fm.liveswitch.DataStream(dataChannelText);
Then, add the DataStream to the downstream connection by providing the DataStream as an additional parameter to the CreateSfuDownstreamConnection method.
Inside the openSfuDownstreamConnection function, update the CreateSfuDownstreamConnection method to add dataStream as an additional parameter.
// Create a SFU downstream connection with remote audio and video and data streams.
SfuDownstreamConnection connection = channel.createSfuDownstreamConnection(remoteConnectionInfo, audioStream, videoStream, dataStream);
// Create a SFU downstream connection with remote audio and video and data stream.
const connection: fm.liveswitch.SfuDownstreamConnection = this.channel.createSfuDownstreamConnection(remoteConnectionInfo, audioStream, videoStream, dataStream);
Uncomment UI Components
Now go to the files for the UI components and uncomment the code for text chat.
In the MainWindow.xaml.cs file, uncomment the code between the <Text Chat> and </Text Chat> tags.
In the TextChannelFragment.java file, uncomment all the code that has been commented out.
Uncomment the commented out code between the <TextChannel and </TextChannel> tags in these files:
ViewModel.swift
TextChannelUI.swift
In the index.ts file, uncomment the codes between the <Text Chat> and </Text Chat> tags.
Run Your App
Tip
In the mobile app, some buttons are hidden. To show hidden buttons, swipe the button (not the screen) from left to right.
Run your app in your project IDE in multiple chat. Click Join. Enter a text message and send it. You should be able to send and receive text messages. For the mobile app, you need to click the Text Chat button to bring up the chat window. Your app UI should look similar to the following: