Code Examples

Complete code examples for common streaming scenarios. Copy and adapt these examples for your app.

Audio Live Room

A complete audio live streaming room with host and audience support.

public class AudioLiveActivity extends AppCompatActivity {

    private ConoStreamManager manager;
    private ConoStreamAudioHelper audioHelper;
    private boolean isHost;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_audio_live);

        // Get data from intent
        isHost = getIntent().getBooleanExtra("is_host", false);
        String serverUrl = getIntent().getStringExtra("server_url");
        String token = getIntent().getStringExtra("token");
        String channelName = getIntent().getStringExtra("channel");

        // Initialize manager
        manager = ((MyApplication) getApplication()).getConoStreamManager();
        audioHelper = new ConoStreamAudioHelper(manager, this);

        // Set up callbacks
        setupEventCallbacks();

        // Join room based on role
        if (isHost) {
            audioHelper.joinAsHost(serverUrl, token, channelName);
        } else {
            audioHelper.joinAsAudience(serverUrl, token, channelName);
        }
    }

    private void setupEventCallbacks() {
        audioHelper.setEventCallback(new ConoStreamEventCallback() {
            @Override
            public void onAudioTrackPublished() {
                showToast("You are now live!");
            }

            @Override
            public void onRemoteAudioTrackSubscribed(String participantId) {
                Log.d("Audio", "Subscribed to: " + participantId);
            }

            @Override
            public void onParticipantJoined(String id, String name) {
                showToast(name + " joined");
            }

            @Override
            public void onParticipantLeft(String id, String name) {
                showToast(name + " left");
            }

            @Override
            public void onConnectionError(String error) {
                showToast("Error: " + error);
                finish();
            }
        });
    }

    // Mute button click handler
    public void onMuteClick(View view) {
        boolean isMuted = manager.isMicrophoneMuted();
        manager.muteMicrophone(!isMuted);
        updateMuteButton(!isMuted);
    }

    // Leave room
    public void onLeaveClick(View view) {
        audioHelper.leaveRoom();
        finish();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (audioHelper != null) {
            audioHelper.leaveRoom();
        }
    }

    private void showToast(String message) {
        runOnUiThread(() -> Toast.makeText(this, message, Toast.LENGTH_SHORT).show());
    }
}

Video Live Room

A video live streaming room with camera preview.

public class VideoLiveActivity extends AppCompatActivity {

    private ConoStreamManager manager;
    private ConoStreamVideoHelper videoHelper;
    private TextureViewRenderer localVideoView;
    private TextureViewRenderer remoteVideoView;
    private boolean isHost;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_live);

        // Find views
        localVideoView = findViewById(R.id.local_video_view);
        remoteVideoView = findViewById(R.id.remote_video_view);

        // Get data from intent
        isHost = getIntent().getBooleanExtra("is_host", false);
        String serverUrl = getIntent().getStringExtra("server_url");
        String token = getIntent().getStringExtra("token");
        String channelName = getIntent().getStringExtra("channel");

        // Initialize
        manager = ((MyApplication) getApplication()).getConoStreamManager();
        videoHelper = new ConoStreamVideoHelper(manager, this);

        // Set up callbacks
        setupEventCallbacks();

        // Join room
        if (isHost) {
            // Host publishes video
            videoHelper.joinAsHost(serverUrl, token, channelName, localVideoView);
            localVideoView.setVisibility(View.VISIBLE);
        } else {
            // Audience just watches
            videoHelper.joinAsAudience(serverUrl, token, channelName);
        }
    }

    private void setupEventCallbacks() {
        videoHelper.setEventCallback(new ConoStreamVideoEventCallback() {
            @Override
            public void onLocalVideoTrackPublished() {
                showToast("Your video is live!");
            }

            @Override
            public void onRemoteVideoTrackSubscribed(String participantId, VideoTrack track) {
                runOnUiThread(() -> {
                    // Display remote video
                    track.addRenderer(remoteVideoView);
                    remoteVideoView.setVisibility(View.VISIBLE);
                });
            }

            @Override
            public void onRemoteVideoTrackUnsubscribed(String participantId) {
                runOnUiThread(() -> {
                    remoteVideoView.setVisibility(View.GONE);
                });
            }

            @Override
            public void onParticipantJoined(String id, String name) {
                showToast(name + " joined");
            }

            @Override
            public void onParticipantLeft(String id, String name) {
                showToast(name + " left");
            }
        });
    }

    // Switch camera button
    public void onSwitchCameraClick(View view) {
        videoHelper.switchCamera();
    }

    // Toggle camera on/off
    public void onToggleCameraClick(View view) {
        boolean isEnabled = videoHelper.isCameraEnabled();
        videoHelper.enableCamera(!isEnabled);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (videoHelper != null) {
            videoHelper.release();
        }
    }
}

Co-hosting Example

Upgrading an audience member to co-host.

public class CoHostActivity extends AppCompatActivity {

    private ConoStreamAudioHelper audioHelper;
    private boolean isCoHost = false;

    // Called when audience wants to become co-host
    public void onRequestCoHostClick(View view) {
        // First, check microphone permission
        if (!hasMicrophonePermission()) {
            requestMicrophonePermission();
            return;
        }

        // Show dialog to host (in your app's logic)
        sendCoHostRequestToHost();
    }

    // Called when host approves the request
    public void onCoHostApproved() {
        // Upgrade to co-host - starts publishing audio
        audioHelper.upgradeToCoHost();
        isCoHost = true;

        // Update UI
        showCoHostUI();
        showToast("You are now a co-host!");
    }

    // Called when co-host wants to step down
    public void onStepDownClick(View view) {
        // Downgrade back to audience
        audioHelper.downgradeToAudience();
        isCoHost = false;

        // Update UI
        showAudienceUI();
        showToast("You are now an audience member");
    }

    private void showCoHostUI() {
        // Show mute button, hide request button, etc.
        findViewById(R.id.btn_mute).setVisibility(View.VISIBLE);
        findViewById(R.id.btn_request_cohost).setVisibility(View.GONE);
        findViewById(R.id.btn_step_down).setVisibility(View.VISIBLE);
    }

    private void showAudienceUI() {
        // Hide mute button, show request button, etc.
        findViewById(R.id.btn_mute).setVisibility(View.GONE);
        findViewById(R.id.btn_request_cohost).setVisibility(View.VISIBLE);
        findViewById(R.id.btn_step_down).setVisibility(View.GONE);
    }
}

PK Battle Example

Split-screen battle between two hosts.

public class PkBattleActivity extends AppCompatActivity {

    private ConoStreamVideoHelper videoHelper;

    // PK views
    private FrameLayout pkLayout;
    private TextureViewRenderer pkLeftView;   // Local host
    private TextureViewRenderer pkRightView;  // Opponent

    private boolean isPkMode = false;

    // Called when PK battle starts
    public void startPkBattle(String opponentUrl, String opponentToken, String opponentChannel) {
        // Switch to PK layout
        pkLayout.setVisibility(View.VISIBLE);
        localVideoView.setVisibility(View.GONE);

        // Initialize PK renderers
        initPkRenderers();

        // Connect to opponent's room
        videoHelper.joinPkOpponentRoom(opponentUrl, opponentToken, opponentChannel);

        // Attach local video to left side
        videoHelper.attachLocalVideoToPkView(pkLeftView);

        // Set callback for opponent video
        videoHelper.setPkOpponentCallback(new PkOpponentCallback() {
            @Override
            public void onPkOpponentVideoReceived(VideoTrack track) {
                runOnUiThread(() -> {
                    track.addRenderer(pkRightView);
                    pkRightView.setVisibility(View.VISIBLE);
                });
            }

            @Override
            public void onPkOpponentOffline(String name) {
                runOnUiThread(() -> {
                    showOpponentOfflineOverlay(name);
                });
            }
        });

        // Attach opponent video to right side
        videoHelper.attachPkRemoteVideoToView(pkRightView);

        isPkMode = true;
    }

    // Called when PK battle ends
    public void endPkBattle() {
        // Leave opponent room
        videoHelper.leavePkOpponentRoom();

        // Cleanup renderers
        videoHelper.cleanupPkRenderers();

        // Switch back to normal layout
        pkLayout.setVisibility(View.GONE);
        localVideoView.setVisibility(View.VISIBLE);

        // Re-attach local video to main view
        videoHelper.attachLocalVideoToView(localVideoView);

        isPkMode = false;
    }

    private void initPkRenderers() {
        // Initialize EGL context for renderers
        EglBase eglBase = EglBase.create();

        pkLeftView.init(eglBase.getEglBaseContext(), null);
        pkLeftView.setMirror(true);
        pkLeftView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL);

        pkRightView.init(eglBase.getEglBaseContext(), null);
        pkRightView.setMirror(false);
        pkRightView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL);
    }

    private void showOpponentOfflineOverlay(String opponentName) {
        // Show "[name] offline" overlay on right side
        TextView offlineText = findViewById(R.id.pk_opponent_offline);
        offlineText.setText(opponentName + " offline");
        offlineText.setVisibility(View.VISIBLE);
    }
}

PK Layout XML

<FrameLayout
    android:id="@+id/pk_layout"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:visibility="gone">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <!-- Left: Local host -->
        <FrameLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <io.conostream.webrtc.TextureViewRenderer
                android:id="@+id/pk_left_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

        </FrameLayout>

        <!-- Divider -->
        <View
            android:layout_width="2dp"
            android:layout_height="match_parent"
            android:background="#FFFFFF" />

        <!-- Right: Opponent -->
        <FrameLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <io.conostream.webrtc.TextureViewRenderer
                android:id="@+id/pk_right_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

            <TextView
                android:id="@+id/pk_opponent_offline"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:textColor="#FFFFFF"
                android:visibility="gone" />

        </FrameLayout>

    </LinearLayout>

</FrameLayout>
ℹ️

Need more examples? Contact us at support@conostream.nl for complete sample projects.