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:
- the session manager, with
VideoKit.sessions()
, to retrieve a session token - the upload manager, with
VideoKit.uploads()
, to upload videos - the video store, with
VideoKit.videos()
, to query, update or delete videos - the stream store, with
VideoKit.streams()
, to manage live streams - the token registry, with
VideoKit.tokens()
, to manage signed playback
These methods return a concrete implementation of three 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 object
Most 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.
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.await()
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.observe { result: Result<Video> -> ...}
// Observe with flat observer, for JS-style callback.
call.observe(object: FlatObserver() {
override fun onResult(result: Video?, error: VideoError?) { ... }
})
// Observe only if successful or failed.
call.observe(object: SuccessObserver() {
override fun onSuccess(result: Video) { ... }
})
call.observe(object: ErrorObserver() {
override fun onError(error: VideoError) { ... }
})
// Kotlin friendly extensions
call.onSuccess { ... }
call.onError { ... }
// Kotlin coroutine extension
suspend fun coroutineFunction() {
val video: Video = VideoKit.videos().update(request).get()
}
If you are using Kotlin coroutines, we provide a handy extension called get which suspends the execution until the call has a successful result, or throws an exception.
suspend fun updateVideo(request: UpdateRequest): Video {
return VideoKit.videos().update(request).get()
}
Listenable objects
All objects that produce events implement the io.video.videokit.common.Listenable<T>
interface,
where T
is a certain type of listener. This interface provides three functions:
addListener(T)
to start listening to eventsremoveListener(T)
to stop listeningaddListener(LifecycleOwner, T)
to start listening for the duration of the lifecycle.
We highly recommend to use the LifecycleOwner
signature as that will ensure that all listeners
are automatically cleared when the scope is destroyed, avoiding hard to catch memory leaks.