Connecting to a Session
This guide walks through the complete flow for joining an EnableX video session from an Android app — from querying available audio devices through publishing your stream and finally disconnecting cleanly. Follow these steps in order; each step depends on the previous one succeeding.
Joining an EnableX session from Android involves these steps in sequence:
- Query audio devices — get the list of available microphones and speakers.
- Create the room object — instantiate
EnxRoomwith your observer implementations. - Initialize the room — call
room.init(context)to prepare the Android media stack. - Register observers — set up all callbacks before connecting.
- Connect to the room — call
room.connect(token, roomInfo, advancedOptions). - Initialize and publish your stream — inside
onRoomConnected, get the local stream and publish it. - Subscribe to remote streams — inside
onStreamAdded, subscribe and attach to your UI. - Disconnect — call
room.disconnect()when the session ends.
If you want a one-call shortcut that wraps steps 2–6, use EnxRtc.joinRoom().
Get Available Audio Devices
EnxRoom.getDevices() returns a list of audio output devices currently connected to the Android device. Use this to let the user choose their preferred audio route — earpiece, speaker, wired headset, or Bluetooth — before or during a session.
- Class:
EnxRoom - Method:
public List<String> getDevices() - Returns: List of device type strings
List<String> devices = room.getDevices();
// Returns a list such as: ["SPEAKER_PHONE", "WIRED_HEADSET", "EARPIECE", "BLUETOOTH", "NONE"]
To get the device currently in use:
String currentDevice = room.getSelectedDevice();
// e.g. "SPEAKER_PHONE"
Device Change Callbacks
If a headset is plugged in or unplugged, or a Bluetooth device connects/disconnects, the SDK notifies your observer:
@Override
public void onDeviceAdded(String deviceName) {
// A new audio device was connected (e.g. Bluetooth headset paired)
Log.d("ENX", "Device added: " + deviceName);
}
@Override
public void onDeviceRemoved(String deviceName) {
// An audio device was disconnected
Log.d("ENX", "Device removed: " + deviceName);
}
@Override
public void onNotifyDeviceUpdate(String deviceName) {
// The active audio device changed
Log.d("ENX", "Now using: " + deviceName);
}
Create and Initialise the Room Object
The EnxRoom constructor takes two observer instances — one for room-level callbacks (EnxRoomObserver) and one for stream-level callbacks (EnxStreamObserver). Your Activity or Fragment typically implements both interfaces.
After instantiating, call room.init(context) to prepare the Android media stack. This step is mandatory before connect().
public class VideoActivity extends AppCompatActivity
implements EnxRoomObserver, EnxStreamObserver {
private EnxRoom room;
private EnxStream localStream;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Step 2: Create the room object
room = new EnxRoom(
this, // EnxRoomObserver
this // EnxStreamObserver
);
// Step 3: Init with Android context
room.init(this);
// Step 4: Register feature observers before connecting
room.setRecordingObserver(this);
room.setTalkerObserver(this);
// Step 5: Connect (see below)
connectToRoom(YOUR_JWT_TOKEN);
}
}
connect(). Callbacks like onRoomConnected and onStreamAdded fire immediately on connection. If observers are registered after connecting, those initial callbacks will be missed.
room.connect()
EnxRoom.connect() authenticates with the JWT token and establishes the signalling channel to the EnableX server. It accepts optional reconnection settings and advanced options.
- Class:
EnxRoom - Method:
public void connect(String token, JSONObject roomInfo, JSONObject advancedOptions)
roomInfo Parameters
| Parameter | Type | Description |
|---|---|---|
allow_reconnect | Boolean | Enable auto-reconnect on network drop. Default: true. |
number_of_attempts | Number | Max reconnect attempts. Default: 3. Minimum: 1. |
timeout_interval | Number | Milliseconds to wait between reconnect attempts. |
audio_only | Boolean | Set true to join as audio-only (no video). |
advancedOptions Parameters
| Option ID | Type | Description |
|---|---|---|
battery_updates | Boolean | Enable battery level update notifications. |
notify-video-resolution-change | Boolean | Enable video resolution change notifications. |
void connectToRoom(String token) {
JSONObject roomInfo = new JSONObject();
roomInfo.put("allow_reconnect", true);
roomInfo.put("number_of_attempts", 3);
roomInfo.put("timeout_interval", 10000);
roomInfo.put("audio_only", false);
JSONArray advancedOptions = new JSONArray();
JSONObject opt1 = new JSONObject();
opt1.put("id", "notify-video-resolution-change");
opt1.put("enable", true);
advancedOptions.put(opt1);
room.connect(token, roomInfo, advancedOptions);
}
// ── Callbacks ───────────────────────────────────────────────────────────────
@Override
public void onRoomConnected(EnxRoom room, JSONObject roomMetaData) {
// Successfully connected — proceed to init and publish local stream
initAndPublishStream();
}
@Override
public void onRoomError(JSONObject errorData) {
// Connection failed
Log.e("ENX", "Room error: " + errorData.toString());
}
@Override
public void onUserConnected(JSONObject userData) {
// A new participant joined the room — update your participant list UI
Log.d("ENX", "User joined: " + userData.optString("name"));
}
@Override
public void onRoomAwaited(JSONObject data) {
// You are waiting for moderator approval (knock room) or
// waiting for moderator to arrive (wait-for-moderator room).
// data: { "event_type": "knock" } or { "event_type": "wait_for_moderator" }
}
@Override
public void onUserAwaited(JSONObject userData) {
// Moderator only: a participant is waiting at the door
// Show approve/deny UI
}
Network Disconnection & Reconnection Callbacks
If the network drops during a session, the SDK fires these callbacks. With auto-reconnect enabled, it attempts to recover silently:
@Override
public void onConnectionLost(JSONObject json) {
// Network connection lost — show "Reconnecting..." UI
}
@Override
public void onConnectionInterrupted(JSONObject json) {
// Connection interrupted (e.g. switched from WiFi to 4G)
}
@Override
public void onUserReconnectSuccess(EnxRoom room, JSONObject roomMetaData) {
// Auto-reconnect succeeded — restore UI
}
@Override
public void onReconnect(String message) {
// Reconnect attempt in progress
}
| Error Code | Description |
|---|---|
| 5073 | Connection switched to alternate network |
| 5074 | Network disconnected; reconnection timed out |
| 5086 | Method called while room is not connected |
| 5087 | Reconnection failed |
Initialize a Local Stream
EnxRoom.getLocalStream() creates a local media stream with the audio, video, and data tracks you configure. Call this inside onRoomConnected, then immediately publish it.
- Class:
EnxRoom - Method:
public EnxStream getLocalStream(JSONObject publishStreamInfo)
publishStreamInfo Options
| Option | Type | Description |
|---|---|---|
audio | Boolean | Include audio track. Default: true. |
video | Boolean | Include video track. Default: true. |
data | Boolean | Include data channel (required for chat/signalling). |
audioMuted | Boolean | Join with microphone muted. |
videoMuted | Boolean | Join with camera off. |
attributes | JSONObject | Custom key/value metadata attached to this stream. |
maxVideoLayers | Number | 1=HD only, 2=HD+SD, 3=HD+SD+LD. More layers = better adaptive quality for receivers. |
Publish the Stream
void initAndPublishStream() {
JSONObject streamInfo = new JSONObject();
streamInfo.put("audio", true);
streamInfo.put("video", true);
streamInfo.put("data", true);
streamInfo.put("audioMuted", false);
streamInfo.put("videoMuted", false);
streamInfo.put("maxVideoLayers", 3); // publish HD + SD + LD layers
JSONObject attributes = new JSONObject();
attributes.put("name", "Alice");
streamInfo.put("attributes", attributes);
// Get the local stream
localStream = room.getLocalStream(streamInfo);
// Attach local stream to your preview SurfaceView/TextureView
localStream.attachRenderer(localPreviewView);
// Publish into the room
room.publish(localStream);
}
// Callback: your stream is now live in the room
@Override
public void onPublishedStream(EnxStream stream) {
Log.d("ENX", "Stream published, ID: " + stream.getId());
}
// Callback: a stream was published — everyone receives this
@Override
public void onStreamAdded(EnxStream stream) {
// Subscribe to remote streams (Step 7)
if (!stream.isLocal()) {
room.subscribe(stream);
}
}
| Error Code | Description |
|---|---|
| 5013 | Failed to publish stream |
| 5015 | Cannot publish without audio, video, or data track |
| 5022 | Cannot publish — floor access not yet granted (Lecture mode) |
| 5023 | Stream is already published |
| 5017 | Failed to access camera and microphone |
Subscribe and Render Remote Streams
When a remote stream becomes available, onStreamAdded fires. Subscribe to it with room.subscribe() and then attach it to an EnxPlayerView in your layout once onSubscribedStream confirms the subscription.
@Override
public void onStreamAdded(EnxStream stream) {
if (!stream.isLocal()) {
room.subscribe(stream);
}
}
@Override
public void onSubscribedStream(EnxStream stream) {
// Successfully subscribed — attach the stream to a player view
runOnUiThread(() -> {
EnxPlayerView playerView = stream.mEnxPlayerView;
remoteVideoContainer.addView(playerView);
});
}
Active Talker Updates
As participants speak, the server updates the active talker list and delivers it through either onActiveTalkerList (when using custom view mode) or onActiveTalkerView (predefined RecyclerView mode). See Stream Management — Active Talkers for full details.
EnxRtc.joinRoom()
EnxRtc.joinRoom() is a convenience method that collapses steps 2–6 into a single call. It creates the room, connects, initializes a local stream, and publishes it automatically. Use it when you want to get into a session as fast as possible with minimal boilerplate.
- Class:
EnxRtc - Method:
public EnxStream joinRoom(String token, JSONObject publishStreamInfo, JSONObject roomInfo, JSONArray advancedOptions)
EnxRtc enxRtc = new EnxRtc(
this, // Context
this, // EnxRoomObserver
this // EnxStreamObserver
);
JSONObject streamInfo = new JSONObject();
streamInfo.put("audio", true);
streamInfo.put("video", true);
streamInfo.put("data", true);
JSONObject roomInfo = new JSONObject();
roomInfo.put("allow_reconnect", true);
roomInfo.put("number_of_attempts", 3);
roomInfo.put("timeout_interval", 10000);
roomInfo.put("activeviews", "view"); // "view" = predefined RecyclerView, "list" = manual list
EnxStream localStream = enxRtc.joinRoom(token, streamInfo, roomInfo, null);
// onRoomConnected and onStreamAdded fire as before
@Override
public void onRoomConnected(EnxRoom room, JSONObject roomMetaData) {
Log.d("ENX", "Joined room: " + roomMetaData.optString("roomId"));
}
activeviews: "view" for the SDK to provide a ready-made RecyclerView of participant videos. Set activeviews: "list" to receive individual streams and build your own layout. You cannot change this after joining.
room.disconnect()
EnxRoom.disconnect() closes the session, releases media tracks, and tears down the signalling connection. Call this when the user leaves the session — in onBackPressed(), a "Leave" button handler, or onDestroy().
- Class:
EnxRoom - Method:
public void disconnect()
room.disconnect();
// Callback: you are now disconnected
@Override
public void onRoomDisConnected(JSONObject json) {
// Clean up UI, navigate back to lobby
runOnUiThread(() -> finish());
}
// Callback: delivered to everyone else in the room
@Override
public void onUserDisConnected(JSONObject userData) {
// Remove the departed user from your participant list
Log.d("ENX", "User left: " + userData.optString("clientId"));
}
| Error Code | Description |
|---|---|
| 5031 | Repeated disconnect() call while previous disconnection is in progress |
| 5032 | disconnect() called after already disconnected |