Skip to main content
Version: Android SDK v1.1.0

Hosting Streams

Hosting live streams means interacting with the io.video.videokit.live.host.StreamHost interface. This interface provides functions to:

  • start, pause and stop the streaming
  • control the camera through StreamHost.camera
  • listen to relevant events through addListener(StreamHostListener), useful for building responsive UIs

Implementations

We provide three StreamHost implementations that you can choose from depending on your case. The usage varies a bit but they all share the same functionality from StreamHost.

### StreamHostController

A StreamHostController is the low level implementation that, unlike the others, is detached from the UI. You will typically hold the controller instance in a ViewModel. Optionally, for perfect state restoration during configuration changes, we also recommend that you use Android's SavedStateHandle and pass it to the controller constructor.

class StreamingViewModel(state: SavedStateHandle) : ViewModel() {

val streamHost = StreamHostController("low-latency", state)

override fun onCleared() {
super.onCleared()
streamHost.release()
}
}

As you can see, the StreamHostController must be released when you're done with it. In order to show the UI and start using the host, you must also call one of the bind methods as soon as you have a view container. For example, with a fragment:

class StreamingFragment : Fragment() {

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.streamHost.bind(this, view.findViewById(R.id.streaming_container))
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
viewModel.streamHost.onRequestPermissionResult(requestCode)
}
}

By passing in the fragment instance, the controller will know how to ask for permissions. We also use the fragment lifecycle to avoid memory leaks, so there's no need to unbind.

StreamHostFragment

The StreamHostFragment is a fragment implemented exactly as described above. It is the recommended implementation as it is very easy to use - no need to release or bind UI, because the fragment owns the views.

You can customize the fragment after it is attached or when creating it, thanks to the StreamHostOptions class:

val options = StreamHostOptions.build {
facing(CameraFacing.FRONT)
flash(CameraFlash.OFF)
zoom(0F)
profile("low-latency")
streamingMode(StreamingMode.CAMERA_AND_AUDIO)
}
val fragment = StreamHostFragment.newInstance(options)

StreamHostView

The StreamHostView is a view that holds a controller, to be used for codebases that do not use fragments at all. Just like the controller:

  • The view must be released with release()
  • You must pass a fragment / activity / lifecycle with bind()

Usage

Once you have chosen the stream host implementation, using it is pretty simple.

Host state

At any moment, you can retrieve the host state using StreamHost.state:

StateDescription
StreamHostState.BUSYThe host is asking the user for permissions, or asking the backend for a Stream object.
StreamHostState.IDLEThe host is not streaming, but it is ready to. Stream might have started and then paused, or never started.
StreamHostState.STREAMINGThe host is currently streaming.

You also have handy functions to navigate through the different states easily:

// start streaming, or resume previously paused stream
streamHost.start()

// pause streaming or toggle
streamHost.pause()
streamHost.toggle()

// stop streaming. The current stream will be marked as finished. Any call to
// start() after this will actually create a new stream object.
streamHost.confirm()

// abort everything. This signals cancellation to the error callback in StreamHostListener.
streamHost.abort()

You can also, at any moment, access the underlying Stream object through StreamHost.stream. This object, especially the playback urls, can be shared to viewers to access the stream.

Configuration

You can use StreamHost.camera to configure everything related to camera, as explained here.

We also offer different StreamHost.streamingMode options to choose between different audio/video sources:

  • StreamingMode.CAMERA_AND_AUDIO: default stream, with camera + microphone
  • StreamingMode.CAMERA_ONLY: no audio stream
  • StreamingMode.AUDIO_ONLY: no video stream

Events

Events are subscribed to through the StreamHost.addListener and StreamHost.removeListener functions.

val streamHost: StreamHost = ...
streamHost.addListener(object : StreamHostListener {

override fun onStreamChanged(stream: Stream) {
// New stream was created! Share with viewers.
}

override fun onError(error: VideoError) {
// Handle error!
}

override fun onResult(stream: Stream) {
// Called after confirm(). Stream is now marked as finished.
}

override fun onStateChanged(@StreamHostState.Value state: Int) {
// State has changed.
}

override fun onDurationChanged(duration: Long) {
// Stream duration has changed. This is called repeatedly as
// streaming progresses.
}

override fun onStreamingModeChanged(@StreamingMode.Value streamingMode: Int) {
// Streaming mode was changed via StreamHost.streamingMode setter.
}
})