Skip to main content

Getting started

Installing the SDK

On your build.gradle file under dependencies block:

dependencies {
// card detection
implementation('io.yesid.sdk.android:card_detection:0.2.3@aar') {
transitive = true
}
// face auth && face enrollment
implementation('io.yesid.sdk.android:face:0.2.5@aar') {
transitive = true
}

implementation ('com.regula.face:api:4.1.+@aar'){
transitive = true
}

implementation 'com.google.code.gson:gson:2.10.1'
implementation "androidx.databinding:databinding-runtime:4.2.2"

repositories {
maven {
url "https://maven.regulaforensics.com/RegulaDocumentReaderWebClient"
}
maven {
url "https://maven.regulaforensics.com/RegulaDocumentReader"
}
maven {
url 'https://jfrog.yesid.tech/artifactory/libs-release-local'
credentials {
username = "${artifactory_user}"
password = "${artifactory_password}"
}
}
}
}

In

android/app/src/main/java/com/yourpackage

Create the following activity files

Card Detection Activity

class CardDetectionActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val onFailure: () -> Unit = {
setResult(Activity.RESULT_CANCELED, Intent().apply {
putExtra("error", "Failed to detect card")
})
finish()
}

val onSuccess: (String) -> Unit = { result ->
CardModule.callback?.invoke(result)
finish()
}

setContent {
MyCardDetectionScreen(
onFailure = onFailure,
onSuccess = onSuccess,
context = this
)
}
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == CardModule.CARD_DETECTION_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
val result = data?.getStringExtra("result")
CardModule.promise?.resolve(result)
} else {
val error = data?.getStringExtra("error")
CardModule.promise?.reject("CARD_DETECTION_ERROR", error)
}
CardModule.promise = null
}
}


companion object {
private const val TAG = "EntryChoiceActivity"
private const val PERMISSION_REQUESTS = 1

private val REQUIRED_RUNTIME_PERMISSIONS =
arrayOf(
Manifest.permission.CAMERA,
)
}
}

@SuppressLint("UnrememberedMutableState")
@Composable
fun MyCardDetectionScreen(onFailure: () -> Unit, onSuccess: (String) -> Unit, context: Activity) {
val ocr = YesidOCRCamera
ocr.userLicense = stringResource(id = R.string.OcrLicenseKey)
val results: MutableState<OCRResponse?> = mutableStateOf(null)
val ocrConfigurationBuilder by mutableStateOf(
OCRConfigurationBuilder.setUserLicense(
stringResource(id = R.string.OcrLicenseKey)
)
.setLensFacing(1)
)
ocr.OCRCamera(
configurationBuilder = ocrConfigurationBuilder,
onResults = {
val entries = it.documentText
val documentImage = it.documentImages["Portrait"]
val documentCardImage = it.documentImages["Document front side"]

// convert bitmap to base64
val documentImageString = documentImage?.let { convertToBase64String(it) }
val documentCardImageString = documentCardImage?.let { convertToBase64String(it) }
val json = Gson().toJson(
mapOf(
"documentImage" to documentImageString,
"documentCardImage" to documentCardImageString,
"documentAllTextData" to entries
)
)
Log.e("OCR", "onResults: $json")
onSuccess.invoke(json)
}
)
}

fun convertToBase64String(
bitmap: Bitmap
): String {
val baos = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val b = baos.toByteArray()
return Base64.encodeToString(b, Base64.DEFAULT)
}

Face Enrollment Activity

class FaceEnrollmentActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val onFailure: (String) -> Unit = {
FaceEnrollmentModule.callback?.invoke(it)
finish()
}

val onSuccess: (String) -> Unit = { result ->
FaceEnrollmentModule.callback?.invoke(result)
finish()
}

setContent {
MyFaceEnrollmentDetectionScreen(
onFailure = onFailure,
onSuccess = onSuccess,
context = this
)
}
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == FaceEnrollmentModule.FACE_ENROLLMENT_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
val result = data?.getStringExtra("result")
FaceEnrollmentModule.promise?.resolve(result)
} else {
val error = data?.getStringExtra("error")
FaceEnrollmentModule.promise?.reject("FACE_ENROLLMENT_DETECTION_ERROR", error)
}
FaceEnrollmentModule.promise = null
}
}
}

@SuppressLint("UnrememberedMutableState")
@Composable
fun MyFaceEnrollmentDetectionScreen(
onFailure: (String) -> Unit,
onSuccess: (String) -> Unit,
context: Activity
) {
val face = YesidFaceEnrollment
val configuration = FaceEnrollmentConfigurationBuilder.setUserLicense(
stringResource(id = R.string.FaceEnrollmentLicenseKey)
)
face.FaceEnrollmentCamera(configuration, onResult = {
try {
val faces = it.faces.map { bitmap -> convertToBase64String(bitmap) }
val json = Gson().toJson(
mapOf(
"faceImages" to faces
)
)
Log.e("FACE", "onResults: $json")
onSuccess.invoke(json)
}catch (e: Exception){
onFailure.invoke(e.message.toString())
}
})
}

Face Auth Activity

class FaceAuthenticationActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val onFailure: (String) -> Unit = {
FaceAuthModule.callback?.invoke(it)
finish()
}

val onSuccess: (String) -> Unit = { result ->
FaceAuthModule.callback?.invoke(result)
finish()
}

val imageData1 = FaceAuthModule.imageData1
val imageData2 = FaceAuthModule.imageData2

setContent {
MyFaceAuthScreen(
onFailure = onFailure,
onSuccess = onSuccess,
context = this,
imageData1 = imageData1,
imageData2 = imageData2
)
}
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == FaceAuthModule.FACE_AUTH_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
val result = data?.getStringExtra("result")
FaceAuthModule.promise?.resolve(result)
} else {
val error = data?.getStringExtra("error")
FaceAuthModule.promise?.reject("FACE_AUTH_ERROR", error)
}
FaceAuthModule.promise = null
}
}



companion object {
private const val TAG = "EntryChoiceActivity"
}
}


@Composable
fun MyFaceAuthScreen(
onFailure: (String) -> Unit,
onSuccess: (String) -> Unit,
context: Activity,
imageData1: String?,
imageData2: String?
) {
val camera = FaceAuthenticationCamera
val configuration =
FaceAuthConfigurationBuilder.setUserLicense("b1c4a278-ac2e-4f38-9447-c5169abf53ec")
val bitmap1 = remember { imageData1?.let { base64ToBitmap(it) } }
val bitmap2 = remember { imageData2?.let { base64ToBitmap(it) } }
val results1 = remember { mutableStateOf<FaceMatchResults?>(null) }
val results2 = remember { mutableStateOf<FaceMatchResults?>(null) }

if (bitmap1 != null && results1.value == null && results2.value == null) {
camera.FaceAuthCamera(
firstImage = bitmap1,
secondImage = bitmap2,
configurationBuilder = configuration,
onMatchResultsFirstImage = { result ->
results1.value = result
},
onMatchResultsSecondImage = { result ->
results2.value = result
},
)
} else {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Column {
CircularProgressIndicator()
Text("Processing...")
}

}
}
LaunchedEffect(key1 = results1.value, key2 = results2.value, block = {
if (results1.value != null && results2.value != null) {
try {
val json = Gson().toJson(
mapOf(
"similarity1" to "${results1.value?.similarity} ",
"similarity2" to "${results2.value?.similarity}"
)
)
Log.e("FACEAUTH", "onResults: $json")
onSuccess.invoke(json)
} catch (e: Exception) {
val json = Gson().toJson(
mapOf(
"similarity1" to "${results1.value?.similarity} ",
"similarity2" to "${results2.value?.similarity}"
)
)
Log.e("FACEAUTH", "onError: $e")
onFailure.invoke(json)
}
}
})
}

private fun base64ToBitmap(base64String: String): Bitmap {
val decodedBytes = Base64.decode(base64String, Base64.DEFAULT)
return try {
BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.size)
} catch (e: Exception) {
Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
}
}

Touchless Activity

class TouchlessActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val onFailure: (String) -> Unit = {
TouchlessModule.callback?.invoke(it)
finish()
}

val onSuccess: (String) -> Unit = { result ->
TouchlessModule.callback?.invoke(result)
finish()
}

setContent {
MyTouchlessDetectionScreen(
onFailure = onFailure,
onSuccess = onSuccess,
context = this
)
}
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == TouchlessModule.TOUCHLESS_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
val result = data?.getStringExtra("result")
TouchlessModule.promise?.resolve(result)
} else {
val error = data?.getStringExtra("error")
TouchlessModule.promise?.reject("CARD_DETECTION_ERROR", error)
}
TouchlessModule.promise = null
}
}

}

@SuppressLint("UnrememberedMutableState")
@Composable
fun MyTouchlessDetectionScreen(
onFailure: (String) -> Unit,
onSuccess: (String) -> Unit,
context: Activity
) {
val touchless = YesidTouchlessCamera
val configuration =
TouchlessConfigurationBuilder.setUserLicense(stringResource(id = R.string.TouchlessLicenseKey))
.setFingerScanDirection(1)
var results: TouchlessResults? by remember { mutableStateOf(null) }
if (results == null) {
touchless.TouchlessCamera(
context = context,
configurationBuilder = configuration,
onResults = {
results = it
})
} else {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Column {
CircularProgressIndicator()
Text("Processing...")
}

}
}
LaunchedEffect(key1 = results, block = {
if (results != null) {
try {
val fullFrameImage =
results?.fullFrameImage?.let { it1 -> convertToBase64String(it1) }
val enhancedFingerprintImages: List<String>? =
results?.enhancedFingerprintImages?.let { it1 ->
it1.map { it2 ->
convertToBase64String(it2)
}
}
val rawFingerprintImages: List<String>? = results?.rawFingerprintImages.let { it1 ->
it1?.map { it2 ->
convertToBase64String(it2)
}
}
val processedFingerprintImages: List<String>? =
results?.processedFingerprintImages?.let { it1 ->
it1.map { it2 ->
convertToBase64String(it2)
}
}
val json = Gson().toJson(
mapOf(
"fullFrameImage" to fullFrameImage,
"enhancedFingerprintImages" to enhancedFingerprintImages,
"rawFingerprintImages" to rawFingerprintImages,
"processedFingerprintImages" to processedFingerprintImages
)
)
Log.e("Touchless", "onResults: $json")
onSuccess.invoke(json)
} catch (e: Exception) {
onFailure.invoke(e.message.toString())
}
}
})
}

Create the following modules

For each SDK in a single file SDKModules.kt

# Card Module
class CardModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
companion object {
const val CARD_DETECTION_REQUEST_CODE = 1
var promise: Promise? = null
var callback: Callback? = null
}

override fun getName(): String {
return "CardModule"
}

@ReactMethod
fun callCardDetection(callback: Callback) {
CardModule.callback = callback
val intent = Intent(currentActivity, CardDetectionActivity::class.java)
currentActivity?.startActivityForResult(intent, CARD_DETECTION_REQUEST_CODE)
}
}

# Face Enrollment Module
class FaceEnrollmentModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
companion object {
const val FACE_ENROLLMENT_REQUEST_CODE = 1
var promise: Promise? = null
var callback: Callback? = null
}

override fun getName(): String {
return "FaceEnrollmentModule"
}

@ReactMethod
fun callFaceEnrollment(callback: Callback) {
FaceEnrollmentModule.callback = callback
val intent = Intent(currentActivity, FaceEnrollmentActivity::class.java)
currentActivity?.startActivityForResult(intent, FACE_ENROLLMENT_REQUEST_CODE)
}
}

# Face Auth Module
class FaceAuthModule(reactContext: ReactApplicationContext) :
ReactContextBaseJavaModule(reactContext) {
companion object {
var imageData2: String? = null
var imageData1: String? = null
const val FACE_AUTH_REQUEST_CODE = 1
var promise: Promise? = null
var callback: Callback? = null
}

override fun getName(): String {
return "FaceAuthModule"
}

@ReactMethod
fun callFaceAuth(imageData1: String, imageData2: String, callback: Callback) {
FaceAuthModule.callback = callback
FaceAuthModule.imageData1 = imageData1
FaceAuthModule.imageData2 = imageData2
val intent = Intent(currentActivity, FaceAuthenticationActivity::class.java)
currentActivity?.startActivityForResult(intent, FACE_AUTH_REQUEST_CODE)
}
}

# Touchless Module

class TouchlessModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
companion object {
const val TOUCHLESS_REQUEST_CODE = 1
var promise: Promise? = null
var callback: Callback? = null
}

override fun getName(): String {
return "TouchlessModule"
}

@ReactMethod
fun callTouchless(callback: Callback) {
TouchlessModule.callback = callback
val intent = Intent(currentActivity, TouchlessActivity::class.java)
currentActivity?.startActivityForResult(intent, TOUCHLESS_REQUEST_CODE)
}
}

Create app package file

Create a file MyAppPackage and include all the modules.

class MyAppPackage : ReactPackage {
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return emptyList()
}

override fun createNativeModules(
reactContext: ReactApplicationContext
): List<NativeModule> {
val modules: MutableList<NativeModule> = ArrayList()
modules.add(CardModule(reactContext))
modules.add(FaceEnrollmentModule(reactContext))
modules.add(FaceAuthModule(reactContext))
modules.add(TouchlessModule(reactContext))
return modules
}
}