View
Integration of MobaiBiometric View with plain camera feed
This example shows how to integrate the Biometric Capture Session to your project. The Biometric Capture Session extracts a frames collection from the camera preview.
This Example app uses ViewBinding, so enable it with the following (at the end of the android{} block):
buildFeatures {
viewBinding true
}
When prompted, click Sync Now, and we will be ready to use the Biometric Capture Session in our app.
Create a capture layout.
In the UI for this example app, we use the following layout structure:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CaptureFragment">
<LinearLayout
android:id="@+id/ll_capture_session_view_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
<Button
android:id="@+id/btn_start_capture"
android:layout_width="170dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:layout_marginTop="300dp"
android:textColor="#DBD7E4"
android:background="@color/colorPrimary"
android:visibility="gone"/>
</FrameLayout>
This LinealLayout hosts MBCaptureSessionView.
<LinearLayout
android:id="@+id/ll_capture_session_view_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
The capture button is enabled when the capture process is not automatic.
<Button
android:id="@+id/btn_start_capture"
android:layout_width="170dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:layout_marginTop="300dp"
android:textColor="#DBD7E4"
android:background="@color/colorPrimary"
android:visibility="gone"/>
Setup CaptureFragment.kt.
CaptureFragment is the host element for the camera preview. And extends from MBCaptureSessionServiceListener.
class CaptureFragment : Fragment(R.layout.fragment_capture), MBCaptureSessionServiceListener {
private var captureSessionService: MBCaptureSessionService? = null
private lateinit var mBinding : FragmentCaptureBinding
@SuppressLint("UnsafeOptInUsageError")
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mBinding = FragmentCaptureBinding.inflate(inflater,container,false)
val options = MBCaptureSessionOptions.Builder().build()
captureSessionService = MBCaptureSessionService(requireContext(), this, options, this)
mBinding.container.addView(captureSessionService!!.getCaptureSessionView())
captureSessionService!!.startCamera()
if (!captureSessionService!!.getAutomaticCapture()) {
mBinding.btnStartCapture.visibility = View.VISIBLE
mBinding.btnStartCapture.setOnClickListener {
captureSessionService!!.startCaptureSession()
}
}
return mBinding.root
}
override fun onCaptureFinished(result: MBCaptureSessionResult?){ }
override fun onCountdown(timeCounter: Int) { }
override fun onValidating(faceStatus: MBFaceStatus) { }
override fun onFailure(errorEnum: MBCaptureSessionError) { }
override fun onCaptureStarted() { }
}
Creates a CaptureFragment viewBinding instance:
private lateinit var mBinding : FragmentCaptureBinding
Create MBCaptureSessionService .This is the communication bridge between the caller and the biometric features.
private var captureSessionService: MBCaptureSessionService? = null
onCreateView method execution.
@SuppressLint("UnsafeOptInUsageError")
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mBinding = FragmentCaptureBinding.inflate(inflater,container,false)
val options = MBCaptureSessionOptions.Builder().build()
captureSessionService = MBCaptureSessionService(requireContext(), this, options, this)
mBinding.container.addView(captureSessionService!!.getCaptureSessionView())
captureSessionService!!.startCamera()
if (!captureSessionService!!.getAutomaticCapture()) {
mBinding.btnStartCapture.visibility = View.VISIBLE
mBinding.btnStartCapture.setOnClickListener {
captureSessionService!!.startCaptureSession()
}
}
return mBinding.root
}
Create an instance of MBCaptureSessionOptions builder. This is the capture session's entry point configuration and it has its own default values . In this case the automaticCapture is set to false and that means the capture is manual.
val options = MBCaptureSessionOptions.Builder().build()
MBCaptureSessionOption.Builder arguments description:
numberOfFrameToCollectDescribes the number of frames to collect during the capture session.frameIntervalAfter collecting the first frame, is the number of frames to skip before collecting a frame.numberOfFramesBeforeCaptureDescribes the number of frames to skip before it starts collecting.automaticCaptureTells whether the capture is automatic or manualtargetResolutionAre the resolution values from the caller device.timeBeforeAutomaticCaptureIs the set time in seconds the capture should wait to start collecting frames.cameraSelectorDescribes whether we want to use a front or rear camera.
MBCaptureSessionInstance initialization.
captureSessionService = MBCaptureSessionService(requireContext(), this, options, this, null)
MBCaptureSessionService arguments.
contextIs an instance of the caller's context needed to implement MBCameraService and MBCaptureSessionView.lifecycleOwnerIs an instance of the caller's life cycle owner needed to implement MBCameraService.optionsRepresents the capture session's entry point configuration for ist correct functioning.callbackUpdates the caller with any change during the whole capture process, including a capture result, it has to be set to null while implementing MBCaptureSessionFragment.
Adds the CaptureSessionView as view child to CaptureFragment.
mBinding.llCaptureSessionViewContainer.addView(captureSessionService!!.getCaptureSessionView())
Starts Camera if camera permission is granted. It is very important to verify the camera permission to get the feature up running.
captureSessionService!!.startCamera()
This block of code enables the capture button if automaticCapture is set to false mining the capture process is manual, or disables it if the automaticCapture is set to true.
if (!captureSessionService!!.getAutomaticCapture()) {
mBinding.btnStartCapture.visibility = View.VISIBLE
mBinding.btnStartCapture.setOnClickListener {
captureSessionService!!.startCaptureSession()
}
}
The function onCaptureFinished gets a result of the capture process if it is successfully finished. result contains a list of nullable Bitmaps. In this case send it as an argument to another screen by using ViewModel and LiveData. And then I start another activity.
override fun onCaptureFinished(result: MBCaptureSessionResult?){ }
onCaptureFinished is executed for MBCaptureSessionService when the capture session has successfully finished. MBCaptureSessionResult arguments:
faceImageA high quality image captured after collecting frames (not implemented).captureSessionDataIs all the collected data in protobuf format (not implemented).framesIs the frame collection.
Function onFailure is executed when the capture process fails. MBCaptureSessionError tells the type of error that occurred.
override fun onFailure(errorEnum: MBCaptureSessionError) { }
MBCaptureSessionError entries:
UNABLE_TO_OPEN_CAMERADescribes failure while opening the cameraUNABLE_TO_COLLECT_FRAMESThe capture has is aborted
Function onValidating is executed when frames are being analyzed.
override fun onValidating(faceStatus: MBFaceStatus) { }
MBFaceStatus entries:
TOO_FAR_AWAYFace is too far awayTOO_CLOSEFace is too closeTOO_FAR_UPFace is too far upTOO_FAR_LEFTFace is too far leftTOO_FAR_DOWNFace is too far downTOO_FAR_RIGHTFace is too far rightNOT_FOUNDFace not foundTOO_MANYToo many facesVALIDFace is valid
Function onCountdown is executed during the automatic capture. timeCounter is the current time in seconds.
override fun onCountdown(timeCounter: Int) { }
The method onCaptureStarted is executed every time a face is valid and starts capturing.
override fun onCaptureStarted() { }