# Android

**BCC Face** es una biblioteca de Android que debe integrarse en una aplicación Android.

Utiliza la cámara del dispositivo para tomar una foto de un rostro con fines biométricos. Proporciona una prueba de vitalidad activa simple, que requiere que la persona sonría durante aproximadamente un segundo y/o mire hacia la derecha o la izquierda. La prueba de vitalidad incluye una opción para pronunciar las instrucciones, facilitando el flujo de trabajo para los usuarios. Además, proporciona una prueba de vitalidad pasiva que puede utilizarse para comprobar si la foto fue tomada de una persona real sin requerir interacción del usuario.

Este manual está actualizado a la versión de BCC Face Mobile Android `4.8.0`.

{% hint style="warning" %}
El **prueba de vitalidad pasiva** está disponible solo a partir de la versión `4.4.0` en adelante.
{% endhint %}

## Requisitos

**BCC Face** es una biblioteca de Android y debe importarse en el proyecto target.

* Versión mínima de Android: *Android 6.0 (SDK 23), "Marshmallow"*.
* El dispositivo móvil debe tener una cámara.
* La aplicación nativa debe construirse con tecnología Android.
* Entorno de desarrollo: se requiere un IDE de Android, como [Android Studio](https://developer.android.com/studio) (recomendado).
* Dependencias externas adicionales:
  * [Google ML Kit](https://developers.google.com/ml-kit/guides), detección de rostros versión 16.0.2;
  * [Lottie](https://lottiefiles.com), versión 3.0.0;
  * [Libyuv-android](https://github.com/xiaoxiaoqingyi/libyuv-android), versión 1.0.0;
* Servicios externos:
  * Firebase, de Google. Se requiere una cuenta, pero no se aplicarán cargos ya que la biblioteca utiliza solo APIs en el dispositivo.

## Instalación

### Agregar la Biblioteca en el Proyecto de la App

BCC Face es proporcionado por Griaule como un `.aar` archivo.

Para agregar las bibliotecas, vaya al directorio de su proyecto, abra la **app** carpeta y cree los directorios: `libs/bccface`. Luego, agregue la `bccfacelib-release.aar` dependencia. La estructura de carpetas debe ser similar a esta:

![](https://2027099991-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5TVzatVMAV3OF5tyA1VF%2Fuploads%2Fgit-blob-c549379fb9b16f47f9db997405fe4476d8ed1014%2FfaceFolderStructre.png?alt=media)

El siguiente paso es hacer que estos archivos sean visibles para las dependencias de gradle. Para ello, agregue la siguiente línea en el archivo `build.gradle (:app)`, en el objeto dependencies:

```groovy
dependencies {
	[...]
	implementation fileTree(dir: 'libs/bccface', include: ['*.aar'])
}
```

Dentro del `build.gradle (:app)` archivo, también agregue las opciones de compilación y establezca Source Compatibility y Target Compatibility para usar 1.8 (Java 8):

```groovy
compileOptions {
	sourceCompatibility = 1.8
	targetCompatibility = 1.8
}
```

### Configurando Google ML Kit

Se recomienda seguir las instrucciones proporcionadas en "[Opción 1: Use el flujo de configuración de la consola de Firebase](https://firebase.google.com/docs/android/setup#console)" de la documentación de Firebase para Android: [Agregar Firebase a su proyecto Android](https://firebase.google.com/docs/android/setup).

Se requiere una cuenta, pero no se aplicarán cargos ya que la biblioteca utiliza solo APIs en el dispositivo: [Ver detalles de precios de Firebase](https://firebase.google.com/pricing/).

Si [Opción 1](https://firebase.google.com/docs/android/setup#console) fue elegida, asegúrese de generar el `google-services.json` archivo y colocarlo en `android/app/` directorio.

Realice cambios en los siguientes archivos:

* `android/build.gradle`

  ```groovy
  buildscript {
  	// ...
  	dependencies {
  		// ...
  		classpath 'com.google.gms:google-services:4.3.3'
  	}
  }
  ```
* `android/app/build.gradle`, agregue al final del archivo:

  ```groovy
  // ...

  apply plugin: 'com.android.application'
  apply plugin: 'kotlin-android'
  apply plugin: 'kotlin-kapt'
  apply plugin: 'com.google.gms.google-services'

  // ...

  android {
  	// ...
  	buildFeatures {
  		viewBinding = true
  		dataBinding = true
  	}
  }

  // ...

  dependencies {
  	// ...
  	implementation 'com.google.firebase:firebase-analytics:17.2.2'
  	// Agregue la línea anterior si usa analytics
  }
  ```

### Configurando todas las dependencias

Realice cambios en los siguientes archivos:

* `android/build.gradle`

  ```groovy
  allprojects {
  	repositories {
  		// ...
  		google()
  		mavenCentral()
  		maven { url 'https://jitpack.io' }
  	}
  }
  ```
* `android/app/build.gradle`

  ```groovy
  // ...
  dependencies {
  	// ...
  	implementation project(path: ':bccfacelib')

  	// ANDROIDX //
  	implementation 'androidx.appcompat:appcompat:1.4.2'
  	implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
  	implementation 'com.google.android.material:material:1.6.1'

  	// Google MLKIT //
  	implementation 'com.google.mlkit:face-detection:16.0.2'

  	// LOTTIE //
  	implementation 'com.airbnb.android:lottie:3.0.0'

  	// LIBYUV //
  	implementation 'com.github.xiaoxiaoqingyi:libyuv-android:v1.0'

  	// CAMERA X //
  	def camerax_version = "1.2.0-rc01"
  	// Biblioteca core de CameraX usando la implementación camera2
  	implementation "androidx.camera:camera-camera2:$camerax_version"
  	// Biblioteca de ciclo de vida de CameraX
  	implementation "androidx.camera:camera-lifecycle:$camerax_version"
  	// Clase View de CameraX
  	implementation "androidx.camera:camera-view:$camerax_version"
  }
  ```

## Uso

### Parámetros y Constructor

Para usar correctamente la biblioteca BCC Face, se requieren algunos parámetros.

A continuación se muestra un ejemplo simple de uso de la biblioteca:

```kotlin
BCCFaceBuilder(this, this).initializeCapture()
```

***

El `BCCFaceBuilder` el constructor de la clase recibe los siguientes parámetros:

* `context: Context` - El contexto de la aplicación.
* `delegate: BCCFaceDelegate` - Interfaz responsable de notificar eventos de captura (p. ej., fallo o éxito).

***

El `BCCFaceBuilder` la clase es responsable de manejar la configuración de uso para `BCCFace`. Los siguientes parámetros son aceptados para configurar la captura biométrica y el comportamiento del software:

* `buildSmileCheck(smileProbability: Float = 0.8f)` - Agrega la sonrisa para la prueba de vitalidad y define el umbral de aceptación. Esta característica está habilitada por defecto.
* `removeSmileCheck()` - Elimina la comprobación de sonrisa para la prueba de vitalidad.
* `buildRotationCheck(livenessConfigList: List<HeadRotationCheck>, headRotationAngle: Float = 20f)` - Define una lista de pruebas de vitalidad para la rotación de la cabeza y el ángulo máximo de rotación. Esta característica está habilitada por defecto. Las opciones de rotación de cabeza son:

  ```kotlin
  enum class HeadRotationCheck {
  	randomRotation,
  	leftRotation,
  	rightRotation;
  }
  ```
* `removeHeadRotation()` - Elimina la rotación de cabeza para la prueba de vitalidad.
* `addPassiveLiveness()` - Agrega la prueba de vitalidad pasiva. Esta función se usa para comprobar si la foto capturada es de una persona real sin requerir ninguna interacción del usuario. Para usar esta función, DEBE deshabilitar las comprobaciones de vitalidad activa (`removeSmileCheck()` y `removeHeadRotation()`) que se agregan por defecto.
* `buildSpeechSettings(speechSettings: SpeechSettings?)` - Define los criterios para el habla de accesibilidad, usando los siguientes parámetros:

  ```kotlin
  class SpeechSettings(
  	val volume: Float = 1.0f,
  	val startsMuted: Boolean = true,
  	val pitch: Float = 1.0f,
  	val speed: Float = 1.0f
  )
  ```

  * `volume` - El volumen de audio entre `0.0` y `1.0`.
  * `startsMuted` - Define si las instrucciones comienzan en silencio o no (`true` para silencio).
  * `pitch` - Define la tonalidad de la voz para las instrucciones entre `0.5` (baja) y `2.0` (alta).
  * `speed` - Define la velocidad de la voz para las instrucciones. Este valor debe ser positivo.

  Los valores predefinidos se pueden acceder a través de la variable estática:

  ```groovy
  class SpeechSettings {
  	companion object {
  		val defaultSpeechSettings = SpeechSettings()
  	}
  }
  ```
* `removeSpeech()` - Elimina el habla de accesibilidad.
* `setReviewEnable(enable: Boolean)` - Define si la pantalla de revisión de captura biométrica está habilitada o deshabilitada.
* `setInstructionEnable(enable: Boolean)` - Define si la pantalla de instrucciones está habilitada o deshabilitada.
* `forceLanguage(language: BCCFaceAPI.BCCLanguages?)` - Fuerza que las instrucciones se muestren en un único idioma. Si el idioma del dispositivo no es compatible, se usará inglés. Los idiomas compatibles son:

  ```kotlin
  enum class BCCLanguages(val locale: Locale) {
  	ptBR(Locale("pt", "br")),
  	enUS(Locale.US),
  	esMX(Locale("es", "mx")),
  	deviceLanguage(Locale.getDefault());
  }
  ```
* `removeLanguage()` - Elimina el idioma forzado.
* `enableFlipCameraButton(enable: Boolean)` - Activa (`true`) o desactiva (`false`) el botón de cambio de cámara (frontal o trasera). Predeterminado: habilitado (`true`).
* `setCameraInitialDirection(CameraFacingDirection.<FRONT or BACK>)` - Define la dirección inicial de la cámara, elija entre:
  * `CameraFacingDirection.FRONT` - Cámara frontal (configuración predeterminada).
  * `CameraFacingDirection.BACK` - Cámara trasera.

***

Todas las configuraciones de dirección de la cámara se obtienen mediante la combinación de los métodos `enableFlipCameraButton` y `setCameraInitialDirection` . Por ejemplo:

* Comenzar con la cámara frontal y habilitar el botón de cambio de cámara:

  ```kotlin
  BCCFaceBuilder(this, this)
  	.enableFlipCameraButton(true)
  	.setCameraInitialDirection(CameraFacingDirection.FRONT)
  ```
* Comenzar con la cámara trasera y deshabilitar el botón de cambio de cámara:

  ```kotlin
  BCCFaceBuilder(this, this)
  	.enableFlipCameraButton(false)
  	.setCameraInitialDirection(CameraFacingDirection.BACK)
  ```

***

Para referencia, aquí hay una lista completa de parámetros y valores predeterminados:

```kotlin
var showPhotoReview: Boolean = false,
var showInstructionScreen: Boolean = false,
var stopVerifyEyesOpenTimeout: Long = 20,
var useICAO: Boolean = false,
var smilingProbabilityThreshold: Float = 0.8f,
var rotateAngle: Float = 20f,
var livenessList: MutableList<LivenessTypes> = mutableListOf(LivenessTypes.SMILE, LivenessTypes.ROTATION_RANDOM),
var language: BCCFaceAPI.BCCLanguages? = null,
var speechSettings: SpeechSettings? = SpeechSettings(),
var activityResults: FaceCaptureActivityResults? = null
```

{% hint style="warning" %}
La prueba de vitalidad activa (usando sonrisa y rotación aleatoria de la cabeza) está habilitada por defecto. Para usar solo la comprobación de vitalidad pasiva, antes de agregarla, es necesario eliminar los métodos de vitalidad activa del constructor:

```kotlin
BCCFaceBuilder(this, this)
	.removeSmileCheck()
	.removeHeadRotation()
	.addPassiveLiveness()
```

{% endhint %}

Aquí hay un fragmento de código para inicializar una captura usando solo la prueba de vitalidad pasiva:

```kotlin
// Desde la Activity deseada...

// Crear el builder
BCCFaceBuilder faceBuilder = new BCCFaceBuilder(this, this);

// Configurar el builder
faceBuilder
	.removeSmileCheck()
	.removeHeadRotation()
	.addPassiveLiveness();

// Inicializar la captura desde el builder
faceBuilder.initializeCapture();
```

### Valores de Retorno

Los resultados de la última captura facial se pueden recuperar usando el método `faceCaptureDidFinish` del `BCCFaceDelegate` interfaz:

```kotlin
fun faceCaptureDidFinish(
	data: BCCFaceReturnData,
	analytics: BCCFaceReturnAnalytics
)
```

El `data` el objeto contiene ambas imágenes capturadas durante el proceso:

```kotlin
class BCCFaceReturnData {
	val originalPhoto: Bitmap?
	val croppedPhoto: Bitmap?

	// Resultado de Vitalidad Pasiva
	val passiveResult: ByteArray?
}
```

Las propiedades devueltas son:

* `originalPhoto` (*imagen*) - La foto original tomada por la cámara.
* `croppedPhoto` (*imagen*) - La foto recortada, que es la imagen del rostro recortada de la foto original.
* `passiveResult` (*ByteArray*) - Contenido de archivo de la colección para vitalidad pasiva. Está presente solo si se capturó con éxito. Es el retorno de la colección para vitalidad pasiva como *JPEG ByteArray*. Estos datos pueden guardarse/exportarse directamente a un archivo o enviarse por la red (para redes: la codificación del sistema puede hacerse fácilmente, p. ej. cadena Base64).

{% hint style="info" %}
El `originalPhoto` y `croppedPhoto` propiedades devuelven `null` cuando la captura se realiza solo para pruebas pasivas (es decir, sin incluir una prueba activa).
{% endhint %}

Si el usuario aborta la captura, cerrando antes de capturar los biométricos, se llamará al método `faceCaptureDidAbort` que puede implementar este método para tratar este escenario.

### Proyecto de Ejemplo

Este es un proyecto de ejemplo funcional para una captura facial usando BCC Mobile Face Android:

```kotlin
package com.example.bccfaceexample

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.example.bccfaceexample.databinding.ActivityMainBinding
import com.griaule.bccfacelib.analytics.BCCFaceReturnAnalytics
import com.griaule.bccfacelib.faceApi.BCCFaceBuilder
import com.griaule.bccfacelib.faceApi.BCCFaceDelegate
import com.griaule.bccfacelib.faceApi.BCCFaceReturnData

class MainActivity : AppCompatActivity(), BCCFaceDelegate {
	private lateinit var binding: ActivityMainBinding

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		binding = ActivityMainBinding.inflate(layoutInflater)
		setContentView(binding.root)
		setupListeners()
	}

	private fun setupListeners() {
		binding.startCaptureButton.setOnClickListener { initializeCapture() }
	}

	private fun initializeCapture() {
		BCCFaceBuilder(this, this)
			.removeSmileCheck()
			.removeHeadRotation()
			.addPassiveLiveness()
			.enableFlipCameraButton(true)
			.enableFlashButton(true)
			.initializeCapture()
	}

	override fun faceCaptureDidFinish(
		data: BCCFaceReturnData,
		analytics: BCCFaceReturnAnalytics
	) {
		// ...
	}

	override fun faceCaptureDidAbort(
		analytics: BCCFaceReturnAnalytics
	) {
		// ...
	}
}
```
