Skip to main content
Version: Android SDK v1.3.0

Concepts

The VideoKit object

Using the core SDK means interacting with the io.video.videokit.VideoKit object. This is the entry point for the whole SDK and gives you access to:

These methods return a concrete implementation of base interfaces (respectively, SessionManager, UploadManager, VideoStore, StreamStore, TokenRegistry) that will let you communicate with our infrastructure and perform all core operations. This design makes it very easy to mock the behavior of these components in your unit tests.

val sessions: SessionManager = VideoKit.sessions()
val uploads: UploadManager = VideoKit.uploads()
val videos: VideoStore = VideoKit.videos()
val streams: StreamStore = VideoKit.streams()
val tokens: TokenRegistry = VideoKit.tokens()

Keep reading to know about the capabilities of each component.

The Call interface

All of our API calls are asynchronous. By default, they are encapsulated in an object called Call, which will give you full control over the action and handling its results.

Coroutine-based projects

For kotlinx.coroutines users, a Call acts similar to a Deferred object. We recommend to use the get() function which will suspend until the result is available, or throw in case of errors. It will also handle cancellation automatically.

suspend fun updateVideo(request: UpdateRequest): Video {
return VideoKit.videos().update(request).get()
}

In addition, most APIs that would return a Call have a *suspending() version which calls get under the hood while keeping the code readable.

Regular projects

If you are not using coroutines, the Call object offers a lot of flexibility. First of all, calls can be canceled:

val call: Call<Video> = VideoKit.videos().update(request)
call.cancel() // user changed its mind

If needed, calls can block the current thread to wait for their result. In this case, the result instance will determine whether the call was successful or not:

val call: Call<Video> = VideoKit.videos().update(request)
val result: Result<Video> = call.getBlocking()
when (result) {
is Result.Success -> {
val video: Video = result.result
// Do something with video
}
is Result.Error -> {
val error: VideoError = result.error
// Handle error
}
}

However, you will typically observe the call so that no thread is blocked. Results are received in the UI thread by default, but different threads can be specified through the handler parameter:

val call: Call<Video> = VideoKit.videos().update(request)

// Observe with plain observer
call.onResult { result: Result<Video> -> ...}

// Observe with flat observer, for JS-style callback.
call.onResult(object: FlatReceiver() {
override fun receiveResult(result: Video?, error: VideoKitException?) { ... }
})

// Observe only if successful or failed.
call.onResult(object: SuccessReceiver() {
override fun receiveSuccess(result: Video) { ... }
})
call.onResult(object: ErrorReceiver() {
override fun receiveError(error: VideoError) { ... }
})

// Kotlin friendly extensions
call.onSuccess { ... }
call.onError { ... }

The Observable interface

All objects that produce events implement the io.video.videokit.common.Observable<T> interface, where T is a certain type of observable. This interface provides a few base functions:

  • addObserver(T) to start observing events
  • removeObserver(T) to stop observing

In addition, observation can be scoped to some 'lifecycle' so that the observer is removed automatically and you don't risk leaking it. See:

  • observeIn(LifecycleOwner, T): ties observation to the lifecycle of the given owner, e.g. a Fragment
  • observeIn(Job, T): ties observation to the lifecycle of the given coroutine Job. You can use currentCoroutineContext().job to retreive the current job.