Skip to main content

Composition

In addition to supporting implementation via Activity (described in quick setup) the SDK also supports implementation via Jetpack Compose.

Basic Usage

Simply call DocumentCameraView in any composition scope to launch the document camera. While basic permission handling is included, we strongly recommend implementing your own permission flow.

@Composable
fun AnyComposable() {
SmartCaptureUiTheme {
DocumentCameraView (
modifier = Modifier
.fillMaxSize(),
onResult = object : DocumentCameraResultHandler {
override fun onResult(
result: DocumentProcessingState.Result,
metadata: DocumentProcessingMetadata?
) {
when (result) {
is DocumentProcessingState.Failure -> {
// Handle failure, e.g. show error message
val errorMessage: String = result.message
val smartCaptureException: SmartCaptureException? = result.smartCaptureException
}
is DocumentProcessingState.Success -> {
// Handle success, e.g. preview or upload captured image
val documentImageBytes = result.bytes
val documentImageBitmap = result.previewBitmap
}
}
}
},
)
}
}

DocumentCameraResultHandler is the easiest way to receive the capture result. This callback provides either a successful capture or an error. Document camera is stopped automatically once DocumentProcessingState.Result is returned; any further actions must be handled manually.

/**
* Callback invoked when the document captures process completes, providing either captured
* image data upon success or error details upon failure.
*
* @param result returns [DocumentProcessingState.Failure] or [DocumentProcessingState.Success]
* @param metadata holds detailed information about document capture process such as how many
* frames were processed and/or duration of the entire process.
*/
interface DocumentCameraResultHandler {
fun onResult(
result: DocumentProcessingState.Result,
metadata: DocumentProcessingMetadata? = null
)
}

As an alternative to this callback, states can be directly observed from the viewModel. See Controlling Via ViewModel.

Configuring DocumentCameraView

To customize behavior, pass a DocumentScannerConfig when calling the Composable. You can control:

  • Whether to show the auto-capture toggle
  • Which side of the document is being captured
  • Which document type is being captured

The document side parameter is used to tailor UI for a specific document capture use case. For example, passing DocumentSide.FRONT will configure animation, instructions and help screen for capturing the front side of the identity document.

The document type parameter when combined with the document side parameter is used to tailor UI for a specific document type. For example, passing DocumentType.PASSPORT and DocumentSide.BACK will configure the animation and instructions for capturing the signature page on passports that contain the signature in a separate page.

💡 Note: DocumentScannerConfig is stateful, updating it will restart the camera with the new configuration. This is useful for multi-step flows like capturing both the front and the back of a document.

/**
* This class is used to configure document camera UI such as
* help screen, instructions, animations and auto capture toggle.
*/
@Parcelize
data class DocumentScannerConfig(
val autoCaptureToggleConfig: AutoCaptureToggleConfig = AutoCaptureToggleConfig.Show,
val documentSide: DocumentSide = DocumentSide.UNSPECIFIED,
) : Parcelable

enum class DocumentSide {
FRONT, BACK, UNSPECIFIED
}

sealed interface AutoCaptureToggleConfig : Parcelable {

@Parcelize
data object Show : AutoCaptureToggleConfig

@Parcelize
data class ShowDelayed(
val durationMs: Long = 15_000L
) : AutoCaptureToggleConfig {
init {
require(durationMs > 0) { "duration must be > 0" }
}
}

@Parcelize
data object Hide : AutoCaptureToggleConfig
}

Controlling the DocumentCameraView

For a more fine-grained control, you can send pause/resume/restart commands to the document camera by passing a SharedFlow<DocumentScannerCommand> as a parameter to the Composable. Pause/resume commands are useful if you want to intercept the scanning process with some custom overlay UI. For example, you can override back handler to show a dialog and while it's being shown the camera should be paused. Restart command might be needed, if you want to restart the capture process without changing the config.

/**
* Document scanner commands for advanced control of the document camera component.
*/
sealed class DocumentScannerCommand {

/**
* Pauses document camera feed and frame processing.
*/
data object Pause : DocumentScannerCommand()

/**
* Resumes document camera feed and frame processing.
*/
data object Resume : DocumentScannerCommand()

/**
* Restarts document camera with the latest [DocumentScannerConfig].
*/
data object Restart : DocumentScannerCommand()
}

Controlling the DocumentCameraView via viewModel

While the above options for configuring and controlling the document camera are offered for simplicity and backwards compatibility, the viewModel for the camera can also be passed in by an implementor. The viewModel exposes multiple states that can be observed and methods that can modify the behavior of the camera. While this fine degree of control can enable a highly responsive UI, irresponsible usage can lead to a worse experience for the end user. Please use this feature responsibly and understand that if this is used to make significant modifications to the user experience it may reduce our ability to help with issues. For an example of how one might use the viewModel to make a more responsive UI, please see the public sample code in github.