Custom capture UI
Use MBCaptureSessionService when your application must own the surrounding controls and layout. The SDK still manages camera capture and validation; your fragment manages presentation and user interaction.
Add a capture container
<FrameLayout
android:id="@+id/capture_view_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Create the capture service
class CustomCaptureFragment : Fragment(R.layout.custom_capture_fragment),
MBCaptureSessionListener,
MBBoundingBoxFaceValidatorListener,
MBCaptureProgressListener,
MBCountDownListener {
private lateinit var captureService: MBCaptureSessionService
@SuppressLint("UnsafeOptInUsageError")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val orientation = when (resources.configuration.orientation) {
Configuration.ORIENTATION_LANDSCAPE -> MBOrientation.LANDSCAPE
else -> MBOrientation.PORTRAIT
}
val options = MBCaptureSessionOptions.Builder()
.captureConstrains(MBCaptureConstrains.V3)
.imageQualityLevel(MBImageQualityLevel.LEVEL_2)
.videoCaptureDuration(2_000)
.cameraQuality(MBCameraOptions(orientation = orientation))
.build()
captureService = MBCaptureSessionService(
requireContext(),
viewLifecycleOwner,
options
).apply {
captureSessionListener = this@CustomCaptureFragment
faceBoundingBoxValidatorListener = this@CustomCaptureFragment
captureProgressListener = this@CustomCaptureFragment
countDownListener = this@CustomCaptureFragment
}
view.findViewById<FrameLayout>(R.id.capture_view_container)
.addView(captureService.getCaptureSessionView())
captureService.startCamera(sessionId)
}
}
The lifecycle owner allows CameraX to stop camera work when the fragment view is destroyed. For V2 and V3, set MBCameraOptions.orientation to match the current screen orientation.
Handle session events
override fun onSuccess(result: MBCaptureSessionResult?) {
result?.let(::upload)
}
override fun onFailure(errorEnum: MBCaptureSessionError) {
showRetry(errorEnum)
}
override fun onStateChanged(stateEnum: MBCaptureState) { }
Show V3 feedback
override fun onValidating(
faceBoxStatus: MBFaceBoundingBoxStatus,
faceGeometry: MBFaceGeometryModel
) {
feedbackLabel.text = feedbackText(faceBoxStatus)
}
Check geometry before lighting so the user receives one clear instruction at a time. See Capture constraints and image quality for the status fields.
Show progress and countdown
override fun onCaptureProgress(captureProgressCounter: Float) {
progressBar.progress = (captureProgressCounter * 100).toInt()
}
override fun onCountdown(timeCounter: Int) {
countdownLabel.text = timeCounter.toString()
}
Manual capture
Set .automaticCapture(false), then call startCaptureSession() from your button after the SDK reports a valid face:
captureButton.setOnClickListener {
captureService.startCaptureSession()
}
Disable the button until validation succeeds to avoid collecting an invalid capture.