Browse SDKs · Flutter
Platform
SDKsFlutter

Send a custom signal

Send and receive custom signaling in a call room with the OpenIM Flutter SDK.

Copy

Use signalingSendCustomSignal() to send lightweight application negotiation data to a call room, such as a raised-hand action, layout-change hint, or application state update. It is not a chat-message API and cannot replace the media engine's data channel.

Send a signal

roomID and customInfo are required strings. To send structured data, define a stable format and serialize it as JSON:

final signal = jsonEncode({
  'version': 1,
  'eventID': eventID,
  'type': 'hand-raised',
  'userID': currentUserID,
  'sentAt': DateTime.now().millisecondsSinceEpoch,
});

await OpenIM.iMManager.signalingManager.signalingSendCustomSignal(
  roomID: roomID,
  customInfo: signal,
);

Future completion means that OpenIMServer accepted the send request; it does not mean that other participants have processed the signal. customInfo can include a protocol version and business idempotency ID. Custom signaling is intended for lightweight, temporary call negotiation; it does not transfer or retain large files, chat history, or durable state.

Receive signals

OnSignalingListener.onReceiveCustomSignal carries CustomSignaling, whose roomID and customInfo are nullable. Validate the room and business protocol before updating the UI:

void handleCustomSignal(CustomSignaling info) {
  final signalRoomID = info.roomID;
  final customInfo = info.customInfo;
  if (signalRoomID != activeRoomID || customInfo == null) return;

  final signal = parseAndValidateCallSignal(customInfo);
  if (hasAppliedSignal(signalRoomID!, signal.eventID)) return;
  applyCallSignal(signal);
}

Future<void> registerCustomSignalListener() {
  return OpenIM.iMManager.signalingManager.setSignalingListener(
    OnSignalingListener(onReceiveCustomSignal: handleCustomSignal),
  );
}

This page is the complete owner of onReceiveCustomSignal. SignalingManager retains only one listener, and a later configuration replaces the previous Dart instance. Combine this callback with every other call callback in one application-level OnSignalingListener; do not configure separate listeners in individual widgets. The SDK has no remove or unset API. When switching accounts, stop dispatching to the previous account's state and replace the listener with the complete instance for the new account.

parseAndValidateCallSignal() parses the JSON structure, protocol version, eventID, type, and application fields. Apply each signal idempotently by roomID:eventID without relying on event order. Custom signaling is not a replayable record of durable state; after reconnecting, reconcile state through a room query or application data.