Skip to main content
Version: 5.x.x

Data Channel - Flutter

The data channel sends text or binary data to all other participants in the room with low delay. Use it for live data that matters only at that moment, such as cursor positions, reactions, typing indicators or game moves.

Messages are not stored on the server. A participant who joins later does not receive the messages that were sent before they joined.

Data Channel or PubSub​

Both send messages to other participants. Choose by what your messages need.

Data channelPubSub
Who receives a messageAll other participantsParticipants subscribed to the topic. With sendOnly, only the participants you list.
Kept for participants who join laterNoYes, when you publish with persist: true
ContentA String or a List<int>, up to 15 KiBA String message, with an optional payload map
Unreliable deliveryYes, with reliable: falseNo

Send a message​

The send() method of the Room class sends a String or a List<int> to all other participants.

  • Call it after the roomJoined event, and await it inside try/catch.
  • reliable: true, the default, resends a message until it arrives, and messages arrive in the order you sent them.
  • reliable: false sends a message once. It can be lost or arrive out of order, so use it for data where a newer message replaces an older one, such as cursor positions.
  • A message can be at most 15 KiB. For text, this is the size of the string in UTF-8.
  • Only participants in Mode.SEND_AND_RECV can send.
import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:videosdk/videosdk.dart';

// Send text, reliably and in order
Future<void> sendHello(Room room) async {
try {
await room.send("Hello everyone");
} on VideoSDKError catch (error) {
debugPrint("Message not sent: ${error.code} ${error.name}");
}
}

// Send binary data once. A newer position replaces a lost one.
Future<void> sendCursorPosition(Room room, double x, double y) async {
final List<int> bytes = utf8.encode(jsonEncode({'x': x, 'y': y}));
try {
await room.send(bytes, reliable: false);
} on VideoSDKError catch (error) {
debugPrint("Position not sent: ${error.code} ${error.name}");
}
}

Errors​

When the message is not sent, send() throws a VideoSDKError:

ErrorWhen
UNKNOWN_ERROR (4000)Before you call join().
ERROR_ACTION_PERFORMED_BEFORE_ROOM_JOINED (3035)While the room is joining, or after it has left.
ERROR_ROOM_RECONNECTING (3065)While the room reconnects. Send the message again after it reconnects.
ERROR_ACTION_NOT_SUPPORTED_IN_MODE (3066)In Mode.RECV_ONLY or Mode.SIGNALLING_ONLY.
ERROR_PAYLOAD_TOO_LARGE (3072)The message is larger than 15 KiB.
ERROR_MEDIA_NOT_READY (3048)The data channel is not open yet.
ERROR_OPERATION_TIMED_OUT (3079)The data channel did not open in time.
ERROR_SEND_FAILED (3070)The data channel could not send the message.

Some of these failures, such as 3070, are also reported on the error event of the room. Handle each failure in one place. A message that is neither a String nor a List<int> throws an ArgumentError.

Receive messages​

The dataReceived event of the Room class fires for every message that another participant sends. You do not receive the messages that you send. Add the handler before you call join(), so that you do not miss any message.

The DataMessage it receives has these properties:

  • senderId: The id of the participant who sent the message.
  • isBinary: true when the sender sent a List<int>.
  • text: The text, when isBinary is false. null for binary data.
  • data: The binary data as a Uint8List, or null for text.
  • reliable: true when the sender used reliable delivery.
  • timestamp: When the message was sent, in milliseconds.
import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:videosdk/videosdk.dart';

void listenForData(Room room) {
room.on(Events.dataReceived, (DataMessage message) {
if (message.isBinary) {
final Uint8List? bytes = message.data;
if (bytes == null) return;
final Map<String, dynamic> position = jsonDecode(utf8.decode(bytes));
debugPrint("${message.senderId} moved the cursor to ${position['x']}, ${position['y']}");
} else {
debugPrint("${message.senderId}: ${message.text}");
}
});
}

API Reference​

The API references for all the methods and events utilized in this guide are provided below.

Got a Question? Ask us on discord