1. Introdução

A BCC Face é um biblioteca de Android feita para ser integrada em uma aplicação Android.

A biblioteca utiliza a câmera do dispositivo para tirar uma foto da face para propósitos biométricos. Ela provê um teste simples de vivacidade ativo, requerendo que a pessoa sorria por alguns segundos e/ou olhe para a direita ou esquerda. O teste de vivacidade inclui uma opção para falar as instruções, facilitando o fluxo para os usuários. Adicionalmente, ela provê um teste de vivacidade passivo que pode ser usado para verificar se a foto foi tirada de uma pessoa real sem requerer interação do usuário.

Esse manual está atualizado para a versão 4.6.1 do BCC Face Mobile Android.

Attention

O teste de vivacidade passivo está disponível somente a partir da versão 4.4.0.

1.1. Requisitos

A BCC Face é uma biblioteca de Android e deve ser importada no projeto-alvo.

  • Versão mínima do Android: Android 6.0 (SDK 23), “Marshmallow”.

  • O aparelho móvel deve possuir uma câmera.

  • O aplicativo nativo deve ser compilado com tecnologia Android.

  • Ambiente de desenvolvimento: Uma IDE Android é necessária, como o Android Studio (recomendado).

  • Dependências externas adicionais:

  • Serviços externos:

    • Firebase, pelo Google. Uma conta é necessária, mas nenhuma cobrança será aplicada, pois a biblioteca usa apenas APIs no dispositivo.

2. Instalação

2.1. Adicionando a biblioteca do projeto do App

A biblioteca BCC Face é fornecida pela Griaule como um arquivo .aar.

Para adicionar a biblioteca, acesse o diretório do seu projeto, abra a pasta app e crie os diretórios libs/bccface. Em seguida, acione a dependência bccfacelib-release.aar. A estrutura de pastas deve ser semelhante a essa:

../../_images/faceFolderStructre1.png

A próxima etapa é tornar esses arquivos visíveis para as dependências do gradle. Para fazer isso, adicione a seguinte linha no arquivo build.gradle (:app) no objeto de dependências:

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

Dentro do arquivo build.gradle (:app), adicione também as opções de compilação e defina a compatibilidade de origem e a compatibilidade de destino para usar 1.8 (Java 8):

compileOptions {
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
}

2.2. Configurando o Google ML Kit

É recomendado seguir as instruções fornecidas na “Option 1: Use the Firebase console setup workflow” da documentação do Firebase para Android: Adicionar o Firebase ao projeto para Android.

Uma conta é necessária, mas nenhuma cobrança será aplicada, pois a biblioteca usa apenas APIs no dispositivo: Veja os detalhes de precificação do Firebase.

Se a Opção 1 foi escolhida, certifique-se de gerar o arquivo google-services.json e colocá-lo no diretório android/app/.

Modifique os seguintes arquivos:

  • android/build.gradle

    buildscript {
        ...
        dependencies {
            ...
            classpath 'com.google.gms:google-services:4.3.3'
        }
    }
    
  • android/app/build.gradle, adicione ao final do arquivo:

    ...
    
    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
    }
    

2.3. Configurando as dependências

Modifique os seguintes arquivos:

  • android/build.gradle

    allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }
    
  • android/app/build.gradle

    ...
    dependencies {
        ...
        implementation project(path: ':bccfacelib')
    
        // ANDROIDX //
        implementation 'androidx.appcompat:appcompat:1.1.0'
        implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
        implementation 'com.google.android.material:material:1.1.0'
    
        // 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"
        // CameraX core library using camera2 implementation
        implementation "androidx.camera:camera-camera2:$camerax_version"
        // CameraX Lifecycle Library
        implementation "androidx.camera:camera-lifecycle:$camerax_version"
        // CameraX View class
        implementation "androidx.camera:camera-view:$camerax_version"
    }
    

3. Uso

3.1. Parâmetros e Construtor

Para usar a biblioteca BCC Face corretamente, certos parâmetros são necessários.

Um exemplo simples de uso de biblioteca é mostrado abaixo:

BCCFaceBuilder(this, this).initializeCapture()

O construtor da classe BCCFaceBuilder recebe os seguintes parâmetros:

  • context:Context - O contexto da aplicação.
  • delegate:BCCFaceDelegate - Interface responsável por notificar os eventos de captura, como falha ou sucesso.

A classe BCCFaceBuilder é responsável por gerenciar as configurações de uso do BCCFace. Os parâmetros a seguir são aceitos para configuração da captura biométrica e comportamento do software:

  • buildSmileCheck(smileProbability: Float = 0.8f) - Adiciona o teste de vivacidade por meio de verificação de sorriso e define o limiar de aceitação. Essa funcionalidade é ativada por padrão.

  • removeSmileCheck() - Remove o teste de vivacidade por meio de sorriso.

  • buildRotationCheck(livenessConfigList: List\<HeadRotationCheck>,
    headRotationAngle: Float = 20f) - Define uma lista de testes de vivacidade para rotação de face e o ângulo máximo de rotação. Essa funcionalidade é ativada por padrão. As opções para rotação de face são:

    enum class HeadRotationCheck {
        randomRotation,
        leftRotation,
        rightRotation;
    }
    
  • removeHeadRotation() - Remove o teste de vivacidade por meio de rotação de face.

  • addPassiveLiveness() - Adiciona o teste de vivacidade passivo. Essa funcionalidade é usada para verificar se a foto capturada é de uma pessoa real sem requerer interação do usuário. Para usar essa funcionalidade, você DEVE desabilitar os testes de vivacidade ativos (removeSmileCheck() e removeHeadRotation()) que são adicionados por padrão.

  • buildSpeechSettings(speechSettings:SpeechSettings?) - Define os critérios para a configuração de acessibilidade (leitura das instruções) usando os seguintes parâmetros:

    class SpeechSettings(
        val volume: Float = 1.0f,
        val startsMuted: Boolean = true,
        val pitch: Float = 1.0f,
        val speed: Float = 1.0f
    )
    
    • volume - O volume do áudio entre 0.0 e 1.0.
    • startsMuted - Define se as instruções iniciarão silenciadas ou não (true para silenciar).
    • pitch - Define o timbre de voz para as instruções entre 0.5 (grave) e 2.0 (agudo).
    • speed - Define a velocidade de leitura das instruções. Este valor deve ser positivo.

    Os valores predeterminados podem ser acessados por meio da seguinte variável estática:

    class SpeechSettings {
        companion object {
            val defaultSpeechSettings = SpeechSettings()
        }
    }
    
  • removeSpeech() - Remove a leitura de acessibilidade.

  • setReviewEnable(enable: Boolean) - Define se a tela de revisão da captura biométrica será habilitada ou não.

  • setInstructionEnable(enable: Boolean) - Define se a tela de instruções será habilitada ou não.

  • forceLanguage(language:BCCFaceAPI.BCCLanguages?) - Força as instruções a serem exibidas em um idioma específico. Se o idioma do dispositivo não for suportado, inglês será usado. Os idiomas suportados são:

    enum class BCCLanguages(val locale: Locale) {
        ptBR(Locale("pt", "br")),
        enUS(Locale.US),
        esMX(Locale("es", "mx")),
        deviceLanguage(Locale.getDefault());
    }
    
  • removeLanguage() - Remove o idioma forçado.

  • enableFlipCameraButton(enable: Boolean) - Ativa (true) ou desativa (false) a presença do botão de troca de câmera (frontal ou traseira). Padrão: ativado (true).

  • setCameraInitialDirection(CameraFacingDirection.<FRONT or BACK>) - Define a direção inicial da câmera, escolher entre:

    • CameraFacingDirection.FRONT - Câmera frontal (definição padrão).
    • CameraFacingDirection.BACK - Câmera traseira.

Todas as configurações de direção da câmera são obtidas por meio da combinação dos métodos enableFlipCameraButton e setCameraInitialDirection. Por exemplo:

  • Iniciar com a câmera frontal e habilitar o botão de troca de câmera:
BCCFaceBuilder(this, this)
    .enableFlipCameraButton(true)
    .setCameraInitialDirection(CameraFacingDirection.FRONT)
  • Iniciar com a câmera traseira e desabilitar o botão de troca de câmera:
BCCFaceBuilder(this, this)
    .enableFlipCameraButton(false)
    .setCameraInitialDirection(CameraFacingDirection.BACK)

Para referência, a lista completa de parâmetros e valores padrão é:

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

Attention

O teste de vivacidade ativo (usando sorriso e rotação aleatória de cabeça) é habilitado por padrão. Para usar apenas o teste de vivacidade passivo, antes de adicioná-lo, é necessário remover os métodos de vivacidade ativa do construtor:

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

Aqui está um trecho de código para iniciar uma captura usando apenas o teste de vivacidade passivo:

// Da Activity desejada...

// Crie o builder
BCCFaceBuilder faceBuilder = new BCCFaceBuilder(this, this);

// Configure o builder
faceBuilder
    .removeSmileCheck()
    .removeHeadRotation()
    .addPassiveLiveness();

// Inicie a captura a partir do builder
faceBuilder.initializeCapture();

3.2. Valores de Retorno

Os resultados da última captura facial podem ser recuperados através do método faceCaptureDidFinish da interface BCCFaceDelegate:

fun faceCaptureDidFinish(
    data: BCCFaceReturnData,
    analytics: BCCFaceReturnAnalytics
)

O objeto data contém ambas as imagens capturadas durante o processo:

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

    // Resultado do teste de vivacidade passivo
    val passiveResult: ByteArray?
}

As propriedades retornadas são:

  • originalPhoto (image) - Foto original tirada pela câmera.
  • croppedPhoto (image) - Foto cortada, que é a imagem da face recortada da foto original.
  • passiveResult (ByteArray) - Conteúdo do arquivo de coleta para teste de vivacidade passivo. Está presente apenas se capturado com sucesso. É o retorno da coleta para teste de vivacidade passivo como JPEG ByteArray. Esses dados podem ser salvos/exportados diretamente para um arquivo ou enviados para a rede (para rede: a codificação do sistema pode ser facilmente feita, por exemplo, uma string Base64).

Note

As propriedades originalPhoto e croppedPhoto retornam nulo (null) quando a captura é realizada apenas para testes passivos (ou seja, sem incluir um teste ativo).

Caso o usuário encerre a aplicação antes de finalizar a captura biométrica, o método faceCaptureDidAbort será chamado. Você pode implementar este método para tratar este cenário.

3.3. Projeto Exemplo

Este é um exemplo de projeto funcional para captura de face utilizando o BCC Mobile Face Android:

package com.example.bccfaceexample

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
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)
            .setInstructionEnable(true)
            .setReviewEnable(true)
            .initializeCapture()
    }

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

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