Skip to content

Guía de integración de biometría - SDK Android

SDK Identia Flow - Android


Descripción

El SDK Identia Flow tiene como propósito capturar una selfie y ambos lados de un documento de identidad para verificar la identidad del usuario.

A partir de la versión 0.0.8 el SDK también permite la lectura NFC del chip de documentos de identidad compatibles con el estándar ICAO 9303, cuando el proceso lo requiere y el dispositivo dispone de NFC (ver Lectura NFC de documentos).

Versión actual: 0.0.8

Dependencia identia:flow:0.0.8
Android mínimo API 21 (Android 5.0)
Novedad principal Lectura NFC de documentos ICAO 9303

Las versiones anteriores a 0.0.8 no incluyen la lectura NFC. Para nuevas integraciones utilice siempre la versión indicada arriba.

Novedades respecto a 0.0.6

  • Lectura NFC de documentos ICAO 9303, sin configuración adicional en su proyecto (ver Lectura NFC de documentos).
  • Respuestas normalizadas en msg. Los errores propios del SDK ya no se entregan en un campo message con texto en español: ahora usan msg con un identificador, igual que las respuestas del flujo biométrico y que el SDK Web (ver Errores nativos del SDK).
  • El SDK ya no muestra mensajes de error al usuario. Se eliminaron los Toast que mostraba ante un error nativo: ahora entrega la respuesta a su aplicación y le devuelve el control, para que usted decida qué mostrar.
  • FlowActivity ya viene declarada en el manifiesto del SDK: no necesita declararla en el AndroidManifest.xml de su aplicación.
  • El permiso de cámara se solicita desde el SDK, con el diálogo del sistema, si no está concedido al abrir FlowActivity (ver Permiso de cámara).
  • Validación del endPoint: solo se cargan destinos https del dominio identia.pe.

Cambios incompatibles al actualizar

Respuestas de error. Si su integración leía el campo message de los errores nativos, debe pasar a leer msg. Los code de esos errores también cambiaron: 501403 para el endPoint inválido y 502400 para el idSession inválido. Las respuestas del flujo biométrico no cambian.

Aviso al usuario. El SDK ya no muestra el Toast que informaba del error. Si su aplicación dependía de ese aviso, ahora debe mostrar su propio mensaje al recibir la respuesta.

Cómo Integrar el SDK

Configuración del Gradle

Repositorios

Además de los repositorios que un proyecto Android trae por defecto, debes agregar el repositorio Maven de Identia. Los tres son necesarios: el SDK se descarga del repositorio de Identia, y sus dependencias se resuelven desde google() y mavenCentral().

En proyectos con Gradle 7 o superior, los repositorios se declaran en settings.gradle:

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url 'https://repo.repsy.io/mvn/identia/identia' }
    }
}

Si tu proyecto todavía los declara en el build.gradle raíz, agrégalo ahí de la misma forma:

allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url 'https://repo.repsy.io/mvn/identia/identia' }
    }
}

mavenCentral() es obligatorio desde la versión 0.0.8

La lectura NFC incorpora dependencias que se resuelven desde Maven Central. Si mavenCentral() no figura entre los repositorios del proyecto, la sincronización de Gradle fallará al no poder resolverlas.

Declarar los repositorios dentro del build.gradle de un módulo puede provocar el error Build was configured to prefer settings repositories over project repositories, según la configuración de repositoriesMode del proyecto. Por eso se recomienda settings.gradle.

Dependencia

En el build.gradle de tu módulo:

dependencies {
    implementation 'identia:flow:0.0.8'
}

Importaciones necesarias

En tu actividad o fragmento donde desees utilizar el SDK, asegúrate de importar:

import pe.identia.flow.FlowActivity

Actualización del AndroidManifest.xml

No es necesario modificar el AndroidManifest.xml de tu aplicación. El SDK ya declara FlowActivity en su propio manifiesto y el sistema de fusión de manifiestos de Android la incorpora automáticamente a tu proyecto.

Si tu aplicación ya venía declarando FlowActivity siguiendo versiones anteriores de esta guía, puedes eliminar esa declaración: mantenerla no causa problemas, pero es redundante.

Permiso de cámara

El permiso android.permission.CAMERA ya viene declarado en el manifiesto del SDK y se incorpora automáticamente a su aplicación mediante la fusión de manifiestos de Android, por lo que no necesita declararlo.

FlowActivity comprueba el permiso al abrirse y, si no está concedido, muestra el diálogo del sistema para solicitarlo. Su aplicación no necesita pedirlo por adelantado:

Situación al abrir FlowActivity Comportamiento del SDK
Permiso ya concedido Carga el flujo de verificación directamente, sin mostrar ningún diálogo.
Permiso no concedido Solicita el permiso. Si el usuario lo concede, el flujo continúa con normalidad; si lo deniega, la actividad se cierra devolviendo el error nativo 401 descrito en Errores nativos del SDK.

Denegación permanente del permiso

Si el usuario ya había denegado el permiso de forma permanente (dos denegaciones previas o la opción No volver a preguntar), Android no vuelve a mostrar el diálogo: la solicitud se resuelve como denegada al instante y su aplicación recibe el error 401 sin que el usuario llegue a ver ninguna pantalla. En ese caso, oriéntelo para que habilite la cámara desde los ajustes de la aplicación.

Solicitarlo por adelantado (opcional)

Aunque el SDK lo gestiona por sí mismo, su aplicación puede solicitar el permiso antes de abrir FlowActivity. Así decide en qué momento se pide y puede mostrar una pantalla explicativa previa, en lugar de que el usuario reciba el diálogo del sistema ya dentro del proceso de verificación. Esto también le permite detectar la denegación permanente antes de iniciar el flujo.

No hay riesgo de solicitudes duplicadas: si el permiso ya está concedido cuando se abre FlowActivity, el SDK no muestra ningún diálogo.

private val requestCamera = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
) { granted ->
    if (granted) {
        abrirFlowActivity()
    } else {
        // Informe al usuario por qué es necesario el permiso.
    }
}

private fun iniciarVerificacion() {
    val concedido = ContextCompat.checkSelfPermission(
        this, Manifest.permission.CAMERA
    ) == PackageManager.PERMISSION_GRANTED

    if (concedido) abrirFlowActivity() else requestCamera.launch(Manifest.permission.CAMERA)
}

Obtención del Token de Acceso desde el Backend

Es esencial que la obtención del token de acceso se realice en el backend de tu aplicación para no exponer las credenciales. Una vez que tu backend haya obtenido el token, puede enviarlo al frontend (tu aplicación Android) de manera segura para que pueda ser utilizado en solicitudes subsiguientes al servidor.

Uso del SDK

Una vez que hayas recibido el token de acceso desde tu backend se deberá crear un proceso biométrico. El Id resultante se deberá asignar al valor "YOUR_OBTAINED_ID" en tu aplicación Android.

Crea un Intent para FlowActivity y pasa los datos necesarios como extras:

Parámetros requeridos: - idSession (String): ID del proceso biométrico obtenido desde el backend - endPoint (String): URL base del servidor (ej: "https://apifacialdev.identia.pe/")

Parámetros opcionales: - style (String): ID de personalización gráfica obtenido desde Backoffice

val intent = Intent(this@MainActivity, FlowActivity::class.java)
intent.putExtra("idSession", YOUR_OBTAINED_ID)
intent.putExtra("endPoint", "https://apifacialdev.identia.pe/")

if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
} else {
    // Maneja el caso en el que no se encuentra la actividad
}

Personalización gráfica

Si has creado una personalización de la interfaz en tu Backoffice, puedes agregarla a tu FlowActivity mediante el parámetro style. El PERSONALIZATION_ID se obtiene directamente del Backoffice. Para hacerlo, agrega el ID de tu personalización como valor de este parámetro en el Intent que inicia la actividad, como se muestra en el siguiente ejemplo:

val intent = Intent(this@MainActivity, FlowActivity::class.java)
intent.putExtra("idSession", YOUR_OBTAINED_ID)  // Corregido a "idSession" para claridad.
intent.putExtra("endPoint", "https://apifacialdev.identia.pe/")
intent.putExtra("style", PERSONALIZATION_ID)

if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
} else {
    // Maneja el caso en el que no se encuentra la actividad
}

Lectura NFC de documentos

Desde la versión 0.0.8, cuando el proceso biométrico lo requiere, el SDK puede leer el chip de documentos de identidad compatibles con el estándar ICAO 9303 (pasaportes, cédulas y permisos de residencia electrónicos).

La lectura la solicita la propia interfaz del proceso: no necesita invocarla ni configurarla desde su aplicación.

No requiere configuración adicional

En Android no es necesario agregar permisos ni declaraciones a su proyecto. El SDK ya incluye en su manifiesto todo lo necesario, y el sistema de fusión de manifiestos de Android lo incorpora automáticamente a su aplicación:

<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="false" />

Su aplicación seguirá disponible en dispositivos sin NFC

La característica se declara con android:required="false", por lo que Google Play no filtrará su aplicación en dispositivos que no cuenten con NFC. En esos dispositivos el resto del flujo biométrico funciona con normalidad.

Requisitos del dispositivo

La lectura NFC solo es posible en dispositivos con hardware NFC nativo y con la función activada por el usuario en los ajustes del sistema. El SDK comprueba ambas condiciones y, cuando no se cumplen, aborta la captura y entrega a su aplicación una respuesta del flujo biométrico con msg: "nfc:sdk:device:hardware". En ninguno de estos casos su aplicación recibe un error nativo:

  • Sin hardware NFC: el SDK lo informa en cuanto la interfaz solicita la lectura.
  • Con NFC presente pero desactivado: el SDK lo informa en lugar de quedarse esperando un documento que nunca podría detectar.
  • NFC desactivado durante la espera: si el usuario apaga el NFC mientras la pantalla de lectura espera el documento (por ejemplo, desde el panel de ajustes rápidos, que no interrumpe el proceso), el SDK detecta el cambio de estado y lo informa igualmente, en lugar de quedarse esperando.

Como la captura se aborta en estos casos, conviene verificar la disponibilidad de NFC antes de abrir FlowActivity e invitar al usuario a activarla, en vez de que descubra el problema ya dentro del proceso de verificación:

val nfcAdapter = NfcAdapter.getDefaultAdapter(this)

when {
    nfcAdapter == null -> {
        // El dispositivo no cuenta con NFC.
    }
    !nfcAdapter.isEnabled -> {
        // NFC presente pero desactivado: sugiera activarlo.
        startActivity(Intent(Settings.ACTION_NFC_SETTINGS))
    }
    else -> {
        // NFC disponible.
    }
}

Recomendaciones de uso

  • La antena NFC se ubica en distintas posiciones según el modelo; normalmente en la parte superior de la cara posterior del dispositivo.
  • El documento debe permanecer inmóvil durante toda la lectura. Moverlo antes de que termine interrumpe la sesión y aborta la captura con nfc:sdk:client:document.
  • Retire fundas gruesas o con elementos metálicos si la detección falla de forma reiterada.

Errores de la lectura NFC

Los errores de la lectura NFC no son errores nativos del SDK: su msg no lleva el prefijo sdk: ni los code de la tabla de Errores nativos del SDK. Llegan en el extra "response" como una respuesta del flujo biométrico, con el prefijo nfc:sdk:.

Un error de lectura aborta la captura: el SDK cierra FlowActivity con el resultado, sin reintentar dentro del mismo flujo. Por ejemplo, un documento retirado del lector antes de que la lectura termine produce:

{
  "result": false,
  "msg": "nfc:sdk:client:document",
  "code": 400
}

Abortar la captura no resuelve el proceso de validación

Estas respuestas interrumpen la captura, pero no dan por finalizado el proceso de validación de identidad ni consumen un intento. Un proceso solo se resuelve cuando las capturas llegan completas al backend y este determina si la persona fue validada o no.

El listado completo de valores está en el Catálogo de mensajes.

Respuestas del SDK

El SDK entrega un único string JSON en el extra "response" del Intent de resultado. Desde la versión 0.0.8, todas las respuestas —las del flujo biométrico y los errores propios del SDK— usan el mismo campo de motivo: msg.

Cómo recibe la respuesta

Utilice ActivityResultLauncher con FlowActivity. Cuando el SDK cierra la actividad con resultado, lea:

val raw = result.data?.getStringExtra("response")

Toda respuesta comparte la misma forma:

Campo Contenido
result true o false
msg Identificador del motivo
code Código asociado al motivo
data Puede incluir process_data u omitirse; siempre null en los errores nativos

El origen se distingue por el valor de msg, no por el campo: los que empiezan por sdk: los genera el propio SDK antes de iniciar la verificación; el resto proviene del flujo biométrico y está documentado en el Catálogo de mensajes.

Ejemplo mínimo de recepción:

resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    val raw = result.data?.getStringExtra("response") ?: return@registerForActivityResult
    val json = JSONObject(raw)
    val msg = json.optString("msg")
    val code = json.optInt("code")

    if (msg.startsWith("sdk:")) {
        // Error nativo del SDK: configuración de la integración o permisos.
    } else {
        // Resultado del flujo biométrico.
    }
}

Errores nativos del SDK

El SDK genera solo estos JSON, antes o sin completar el flujo biométrico. Siempre incluyen result: false y data: null.

msg code Cuándo
sdk:camera:denied 401 El usuario denegó el permiso de cámara solicitado por el SDK
sdk:endpoint:invalid 403 endPoint no es un dominio identia.pe válido
sdk:idsession:invalid 400 idSession no cumple el formato esperado

Los identificadores y sus code son estables entre versiones, de modo que su backend puede tratarlos con una sola lógica.

El SDK no muestra ningún mensaje al usuario

Ante cualquier error, el SDK no presenta avisos, diálogos ni Toast: cierra FlowActivity, entrega la respuesta en el extra "response" y devuelve el control a su aplicación. Qué se le muestra al usuario, y si conviene reintentar, lo decide usted a partir del msg.

Permiso de cámara denegado:

{
  "result": false,
  "msg": "sdk:camera:denied",
  "code": 401,
  "data": null
}

idSession inválido:

{
  "result": false,
  "msg": "sdk:idsession:invalid",
  "code": 400,
  "data": null
}

endPoint inválido:

{
  "result": false,
  "msg": "sdk:endpoint:invalid",
  "code": 403,
  "data": null
}

En estos casos el SDK también devuelve Activity.RESULT_OK con el extra "response".

Flujo biométrico (respuesta con msg)

Cuando el usuario completa o interrumpe la verificación, el SDK reenvía un JSON con msg (y, según el caso, id, confidence, process_data, etc.) sin alterarlo. El motivo del rechazo o del error de captura es el valor de msg.

Referencias:

Ejemplo de rechazo biométrico:

{
  "result": false,
  "msg": "liveness:selfie",
  "code": 200,
  "id": "abc123...",
  "confidence": 0.12
}

En las respuestas del flujo biométrico, result: false con code: 200 puede indicar un challenge no superado; el code describe el estado del resultado, no necesariamente un HTTP 200.

Cierre sin JSON en "response"

En algunos cierres de FlowActivity el integrador puede recibir resultCode != Activity.RESULT_OK o un extra "response" nulo o vacío (por ejemplo, si el usuario abandona la pantalla o la navegación sale de la URL del proceso). En esos casos el SDK no entrega un JSON de resultado biométrico ni un error nativo de la tabla anterior.

Errores frecuentes y soluciones

1. Problemas de Sincronización del Gradle

Error: Cambios en el build.gradle no se reflejan, o la dependencia del SDK no se resuelve correctamente.

Solución:

  1. Ejecuta "Clean Project" y luego "Rebuild Project" en Android Studio.
  2. Verifica que tu conexión a Internet esté activa y funcione correctamente.
  3. Asegúrate de que la URL del repositorio Maven esté escrita correctamente en el build.gradle.

2. Errores de Importación

Error: La clase FlowActivity no se encuentra o no se puede importar.

Solución:

  1. Confirma que la dependencia del SDK se ha añadido correctamente en el build.gradle.
  2. Realiza una sincronización del Gradle y reconstruye el proyecto.

3. Problemas de Ejecución de FlowActivity

Error: La aplicación se cierra o no inicia FlowActivity al intentar ejecutar el Intent.

Solución:

  1. Asegúrate de que todos los datos necesarios se pasan correctamente al Intent.

4. Errores de Permiso de Cámara

Error: El SDK devuelve JSON con msg: "sdk:camera:denied" y code: 401 (véase Errores nativos del SDK), en ocasiones sin que el usuario haya visto ningún diálogo.

Solución:

  1. No es necesario declarar el permiso en tu AndroidManifest.xml: ya viene incluido en el manifiesto del SDK. Tampoco necesitas solicitarlo, porque FlowActivity lo pide al abrirse (véase Permiso de cámara).
  2. Si el error llega sin que aparezca el diálogo del sistema, lo más probable es que el usuario haya denegado el permiso de forma permanente en un intento anterior. Diríjelo a los ajustes de la aplicación para habilitar la cámara.
  3. Contempla siempre la respuesta nativa 401 para el caso en que el usuario deniegue el permiso.

5. Problemas de Conectividad con el Backend

Error: No se recibe el token de acceso desde el backend.

Solución:

  1. Verifica la conectividad de red de la aplicación.
  2. Asegúrate de que el endpoint del backend esté operativo y accesible.
  3. Revisa la implementación del servicio que obtiene el token para identificar posibles errores.

6. Problemas de Respuesta del SDK

Error: Respuestas inesperadas o nulas, o la aplicación deja de reconocer el motivo del error tras actualizar a 0.0.8.

Solución:

  1. Desde 0.0.8 el motivo viaja siempre en msg: las versiones anteriores entregaban los errores nativos en un campo message con texto en español. Si su integración leía message, actualícela según Errores nativos del SDK.
  2. Si no hay extra "response", revisa Cierre sin JSON en "response".
  3. Verifica que idSession y endPoint cumplen el formato esperado antes de abrir FlowActivity.

7. Problemas de Rendimiento o Inestabilidad

Error: La aplicación se vuelve lenta o inestable después de integrar el SDK.

Solución:

  1. Revisa el uso de memoria y CPU de tu aplicación para identificar posibles fugas de memoria o bucles infinitos.
  2. Actualiza a la última versión del SDK, ya que puede incluir optimizaciones y correcciones de errores.

8. Errores de Compilación Después de Actualizaciones

Error: Errores de compilación después de actualizar el SDK.

Solución:

  1. Limpia el proyecto (Clean Project) y reconstrúyelo (Rebuild Project).
  2. Revisa las notas de la versión del SDK para cualquier cambio en la API o en las dependencias.

9. El Documento No Es Detectado por NFC

Error: La pantalla de lectura NFC permanece esperando y el documento nunca es detectado.

Solución:

  1. Confirma que estás utilizando la versión 0.0.8 o superior del SDK: las anteriores no incluyen la lectura NFC.
  2. Verifica que el dispositivo cuente con NFC y que la función esté activada en los ajustes del sistema. Si está desactivada, el SDK lo informa a la interfaz del proceso (véase Requisitos del dispositivo).
  3. Comprueba la posición del documento respecto de la antena NFC y mantenlo inmóvil durante toda la lectura.
  4. Ten en cuenta que la lectura NFC requiere un dispositivo físico: no funciona en emuladores.

Incluir esta sección en la documentación o FAQ de tu SDK ayudará a los desarrolladores a resolver rápidamente problemas comunes, mejorando la experiencia general de integración del SDK Identia Flow.