# Android

**BCC Face** is an Android library meant to be integrated into an Android application.

It uses the device’s camera to take a picture of a face for biometric purposes. It provides a simple active liveness test, requiring the person to smile for about a second and/or look to the right or left. The liveness test includes an option to speak the instructions, facilitating the workflow for users. Additionally, it provides a passive liveness test that can be used to check if the photo was taken from a real person without requiring user interaction.

This manual is updated to BCC Face Mobile Android version `4.11.3`.

{% hint style="warning" %}
The **passive liveness test** is available only from version `4.4.0` onwards.
{% endhint %}

## Requirements

BCC Face is an Android library and must be imported into the target project.

* Minimum Android version: Android 6.0 (SDK 23), "Marshmallow".
* The mobile device must have a camera.
* The native application must be built using Android technology.
* Development environment: an Android IDE is required, such as Android Studio (recommended).
* Additional external dependencies:
  * Google ML Kit, face detection version 16.1.7;
  * Lottie, version 3.0.0;
  * RootBeer, version 0.1.1;
  * Gson, version 2.8.5;
  * Google Tink, version 1.11.0;
  * Material Components, version 1.6.1.
* External services:
  * Firebase, by Google. An account is required, but no charges will apply since the library only uses on-device APIs.

## Installation

### Adding the Library in the App Project

BCC Face is provided by Griaule as a `.aar` file.

To add the libraries, go to your project directory, open the **app** folder and create the directories: `libs/bccface`. Then, add the `bccfacelib-release.aar` dependency. The folder structure must similar to this:

![](/files/EBK7mgGG4glfHItYhyic)

The next step is to make these files visible to the gradle dependencies. To do this, add the following line in the file `build.gradle (:app)`, in the dependencies object:

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

Inside the `build.gradle (:app)` file, also add the compile options and set Source Compatibility and Target Compatibility to use Java 17:

```groovy
compileOptions {
	sourceCompatibility JavaVersion.VERSION_17
	targetCompatibility JavaVersion.VERSION_17
}
```

### Setting up Google ML Kit

It is recommended to follow the instructions provided in "[Option 1: Use the Firebase console setup workflow](https://firebase.google.com/docs/android/setup#console)" of the Firebase for Android documentation: [Add Firebase to your Android project](https://firebase.google.com/docs/android/setup).

An account is required, but no charges will be applied since the library uses only on-device APIs: [See Firebase pricing details](https://firebase.google.com/pricing/).

If [Option 1](https://firebase.google.com/docs/android/setup#console) was chosen, make sure to generate the `google-services.json` file and to place it in `android/app/` directory.

Make changes to the following files:

* `android/build.gradle`

  ```groovy
  buildscript {
  	// ...
  	dependencies {
  		// ...
  		classpath 'com.google.gms:google-services:4.4.2'
  	}
  }
  ```
* `android/app/build.gradle`, add to the bottom of the file:

  ```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'
  	// Add line above using analytics
  }
  ```

### Setting up all dependencies

Make changes to the following files:

* `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.7.0'
  	implementation 'androidx.core:core-ktx:1.13.1'
  	implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

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

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

  	// CAMERA X //
  	def camerax_version = "1.5.1"
  	implementation "androidx.camera:camera-camera2:$camerax_version"
  	implementation "androidx.camera:camera-lifecycle:$camerax_version"
  	implementation "androidx.camera:camera-view:$camerax_version"

  	// MATERIAL //
  	implementation 'com.google.android.material:material:1.6.1'
  }
  ```

## Usage

### Parameters and Constructor

To properly use the BCC Face library, there are some required parameters.

A simple library usage example is shown below:

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

***

The `BCCFaceBuilder` class constructor receives the following parameters:

* `context: Context` - The application context.
* `delegate: BCCFaceDelegate` - Interface responsible for notifying capture events (e.g. failure or success).

***

The `BCCFaceBuilder` class is responsible for handling the usage configuration for `BCCFace`. The following parameters are accepted for configuring biometric capture and software behavior:

* `buildSmileCheck(smileProbability: Float = 0.8f)` - Adds smile for liveness test and defines the acceptance threshold. This feature is enabled by default.
* `removeSmileCheck()` - Removes smile for liveness check.
* `buildRotationCheck(livenessConfigList: List<HeadRotationCheck>, headRotationAngle: Float = 20f)` - Defines a list of liveness tests for head rotation and max rotation angle. This feature is enabled by default. The head rotation options are:

  ```kotlin
  enum class HeadRotationCheck {
  	randomRotation,
  	leftRotation,
  	rightRotation;
  }
  ```
* `removeHeadRotation()` - Removes head rotation for liveness check.
* `addPassiveLiveness()` - Adds the passive liveness test. This feature is used to check if the captured photo is from a real person without requiring any user interaction. To use this feature, you MUST disable the active liveness checks (`removeSmileCheck()` and `removeHeadRotation()`) that are added by default.
* `buildSpeechSettings(speechSettings: SpeechSettings?)` - Defines the criteria for accessibility speech, using the following parameters:

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

  * `volume` - The audio volume between `0.0` and `1.0`.
  * `startsMuted` - Defines whether the instructions start muted or not (`true` for muted).
  * `pitch` - Defines the voice pitch for the instructions between `0.5` (low) and `2.0` (high).
  * `speed` - Defines the voice speed for the instructions. This value must be positive.

  The pre-defined values can be accessed through the static variable:

  ```groovy
  class SpeechSettings {
  	companion object {
  		val defaultSpeechSettings = SpeechSettings()
  	}
  }
  ```
* `removeSpeech()` - Removes accessibility speech.
* `setInstructionEnable(enable: Boolean)` – Defines whether the instruction screen is enabled or disabled.
* `forceLanguage(language: BCCFaceAPI.BCCLanguages?)` - Forces the instructions to be shown in a single language. If the device language is not supported, English will be used. The supported languages are:

  ```kotlin
  enum class BCCLanguages(val locale: Locale) {
  	ptBR(Locale("pt", "br")),
  	enUS(Locale.US),
  	esMX(Locale("es", "mx")),
  	deviceLanguage(Locale.getDefault());
  }
  ```
* `removeLanguage()` - Removes the forced language.
* `enableFlipCameraButton(enable: Boolean)` - Activates (`true`) or deactivates (`false`) the camera flip button (front or back camera). Default: enabled (`true`).
* `enableFlashButton(enable: Boolean)` – Enables (`true`) or disables (`false`) the flash button on the rear camera. Default: disabled (`false`).
* `enableManualCapture(enable: Boolean)` – Enables (`true`) or disables (`false`) the manual capture button, allowing the user to bypass automatic capture checks. When performing a manual capture, the user will be able to review the captured photo before completing the process.
* `enableIntegrityValidation(clientSecret: ByteArray, nonce: ByteArray)` – Enables integrity validation for passive liveness detection, adding an extra security layer to ensure payload integrity.
* `setImageCompressionFormat(format: ImageCompressionFormat)` – Defines the compression format for a passive liveness capture. Available options are `ImageCompressionFormat.JPEG` (default) or `ImageCompressionFormat.JPEG200`.
* `setCameraInitialDirection(CameraFacingDirection.<FRONT or BACK>)` – Defines the initial camera direction. Choose between:
  * `CameraFacingDirection.FRONT` – Front camera (default setting).
  * `CameraFacingDirection.BACK` – Rear camera.

***

All camera direction settings are obtained through the combination of the `enableFlipCameraButton` and `setCameraInitialDirection` methods. For example:

* Start with the front camera and enable the camera flip button:

  ```kotlin
  BCCFaceBuilder(this, this)
  	.enableFlipCameraButton(true)
  	.setCameraInitialDirection(CameraFacingDirection.FRONT)
  ```
* Start with the back camera and disable the camera flip button:

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

***

For reference, here is a full list of parameters and default values:

```kotlin
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),
var rotationChecks: MutableList<HeadRotationCheck> = mutableListOf(HeadRotationCheck.randomRotation),
var language: BCCFaceAPI.BCCLanguages? = null,
var speechSettings: SpeechSettings? = SpeechSettings(),
var activityResults: FaceCaptureActivityResults? = null,
var enableFlipCameraButton: Boolean = false,
var enableManualCapture: Boolean = false,
var initCameraFaceDirection: Int = CameraSelector.LENS_FACING_FRONT,
var imageCompressionFormat: ImageCompressionFormat = ImageCompressionFormat.JPEG,
var integrityValidationData: IntegrityValidationData? = null
```

{% hint style="warning" %}
The active liveness test (using smile and random head rotation) is enabled by default. To only use the passive liveness check, before adding it, it is necessary to remove the active liveness methods from the constructor:

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

{% endhint %}

Here is a code snipped to initialize a capture using only the passive liveness test:

```kotlin
// From the desired Activity...

// Create the builder
BCCFaceBuilder faceBuilder = new BCCFaceBuilder(this, this);

// Setup the builder
faceBuilder
	.removeSmileCheck()
	.removeHeadRotation()
	.addPassiveLiveness();

// Initialize the capture from the builder
faceBuilder.initializeCapture();
```

### Return Values

The results from the last facial capture can be retrieved using the `faceCaptureDidFinish` method from the `BCCFaceDelegate` interface:

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

The `data` object contains both images captured during the process:

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

	// Passive Liveness Result
	val passiveResult: ByteArray?
}
```

The returned properties are:

* `originalPhoto` (*image*) - The original photo taken by the camera.
* `croppedPhoto` (*image*) - The cropped photo, which is the face image cropped from the original photo.
* `passiveResult` (*ByteArray*) - File content of the collection for passive liveness. It is present only if successfully captured. It is the return of the collection for passive liveness as *JPEG ByteArray*. This data can be saved/exported directly to a file or sent to the network (for networking: system encoding can be easily done, e.g. Base64 string).

{% hint style="info" %}
The `originalPhoto` and `croppedPhoto` properties return `null` when the capture is performed only for passive tests (i.e., without including an active test).
{% endhint %}

If the user aborts the capture, closing before capturing the biometrics, the method `faceCaptureDidAbort` will be called. You can implement this method to treat this scenario.

### Sample Project

This is a functional sample project for a face capture using 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
	) {
		// ...
	}
}
```

## Agent Instructions: Querying This Documentation <a href="#agent-instructions-querying-this-documentation" id="agent-instructions-querying-this-documentation"></a>

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.griaule.com/sdks/bcc-face/bccmobilefaceandroid.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.griaule.com/sdks/en/bcc-face/bccmobilefaceandroid.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
