Skip to main content
Version: Android SDK v1.3.0

Implementations

We provide a few Recorder implementations that you can choose from depending on your case. Using them is a bit different but they all share the same functionality from the Recorder interface.

  • A default implementation called DefaultRecorder
  • A few UI-specific implementations. These can be found in the io.video:videokit-recorder-ui module and generally implement Recorder by delegation to some DefaultRecorder under the hood.

The default recorder

DefaultRecorder is the low level implementation that, unlike the others, is detached from the UI. You will typically hold the default instance in the "view model" layer of your app, but you are free to do otherwise.

The recorder offers many constructors that should fit your use case:

  • DefaultRecorder(Context, SavedStateHandle?): to be used from AAC ViewModels, which can receive a SavedStateHandle into their constructor.
  • DefaultRecorder(ComponentActivity): to be used from activities.
  • DefaultRecorder(Fragment): to be used from fragments.
  • DefaultRecorder(Context, LifecycleOwner?, SavedStateRegistry, ActivityResultCaller): lower level constructor.

For example, in the view model scenario:

class RecordViewModel(app: Application, state: SavedStateHandle) : AndroidViewModel(app) {

val recorder = DefaultRecorder(app, state)

override fun onCleared() {
super.onCleared()
recorder.destroy()
}
}

As you can see, the DefaultRecorder must be destroyed when you're done with it.

Showing the UI

The default recorder creates and caches an android.view.View with the content to be shown (camera and video preview). In order to show the UI in your app, make sure to add this view to some parent view in your hierarchy:

val parentView: ViewGroup = findViewById(R.id.recorder_container)
parentView.addView(recorder.view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)

Enabling activity results

Our recorder needs access to an ActivityResultCaller to support some features like permission requests and gallery imports. By default, it will try to determine an ActivityResultCaller from the constructor parameters. But depending on the constructor used, you might have to manually pass one:

if (recorder.activityResultCaller == null) {
recorder.activityResultCaller = ...
}

Note that ActivityResultCaller is implemented by activities and fragments, so the SDK is always able to determine it automatically for activity and fragment constructors.

videokit-recorder-ui module: the recorder fragment

The RecorderFragment is a fragment implemented as described above, hosting the recorder in a view model. It is slightly easier to use since there is no need to release or care about the UI.

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

val options = RecorderFragment.Options.build {
overlay(R.layout.custom_controls)
direction(CameraDirection.Front)
flash(CameraFlash.Off)
uploadParams(UploadParams(title = "Video Title"))
saveToGallery(true)
maxDuration(30000L)
}
val recorder = RecorderFragment.newInstance(options)

videokit-recorder-ui module: the recorder view

The RecorderView is a view that holds a default recorder, to be used for codebases that do not use fragments at all. Like the fragment, this is a very simple option, although it has the drawback that the recorder state will not be kept across activity restoration.

videokit-recorder-ui module: Jetpack Compose recorder

For Jetpack Compose users, we provide two useful functions.

First, rememberRecorder: use this to efficiently create a DefaultRecorder and scope it to the composition. Under the hood, we take care about state restoration and lifecycle management.

Lastly, a Recorder() composable which accepts the recorder from above:

@Composable
fun RecorderScreen(modifier: Modifier = Modifier) {
val recorder = rememberRecorder()
Box(modifier) {
Recorder(recorder, Modifier.fillMaxSize())
// Overlays here...
}
}

Note that, despite the reactive composable, management of the recorder APIs must be done through the imperative APIs of DefaultRecorder. In fact, the default recorder is better hosted somewhere in the view model layer for ease of access and management.