JAAK Stamps SDK Android
Introduccion
El JAAK Stamps SDK es una solucion completa para captura profesional de documentos de identidad en aplicaciones Android. El SDK automatiza todo el proceso de captura, desde la deteccion del documento hasta el recorte y extraccion de informacion visual.
Caracteristicas principales
- Captura guiada con instrucciones visuales en tiempo real
- Deteccion automatica de tipo de documento (frente/reverso)
- Recorte inteligente del documento
- Extraccion automatica del rostro del documento
- Validacion de calidad de imagen
- Soporte para INE, IFE, Pasaporte, Licencias, Cedulas
- Interfaz de usuario personalizable
- Optimizado para todos los rangos de dispositivos
Que hace el SDK
El SDK guia al usuario paso a paso para capturar documentos de identidad con calidad profesional:
- Detecta el documento automaticamente usando la camara
- Guia al usuario con instrucciones visuales (acercar, alejar, mantener estable)
- Valida la calidad en tiempo real (iluminacion, nitidez, alineacion)
- Captura automaticamente cuando detecta condiciones optimas
- Recorta el documento eliminando fondo y bordes innecesarios
- Extrae el rostro de la foto del documento (si esta presente)
- Determina si necesita reverso (INE/IFE) o solo frente (Pasaporte)
- Entrega multiples versiones de cada imagen (original, recortada, rostro)
Requisitos Previos
Requisitos Tecnicos
| Componente | Version Requerida | Notas |
|---|---|---|
| Android Studio | Iguana o superior | IDE recomendado |
| Gradle | 8.4+ | Sistema de compilacion |
| Kotlin | 1.9.22+ | Compatible con Java |
| Android API minima | 23 (Android 6.0) | Dispositivos soportados |
| Android API objetivo | 33+ (Android 13+) | Version recomendada |
| Hilt (Dagger) | 2.48 | Framework de inyeccion de dependencias |
Requisitos Previos
Requisitos Técnicos
| Componente | Versión Requerida | Notas |
|---|---|---|
| Android Studio | Iguana o superior | IDE recomendado |
| Gradle | 8.4+ | Sistema de compilación |
| Kotlin | 1.9.22+ | Lenguaje de programación |
| Android API mínima | 22 (Android 5.1) | Dispositivos soportados |
| Android API objetivo | 33+ (Android 13+) | Versión recomendada |
| Java Compatibility | 18 | Nivel de compatibilidad |
Credenciales Necesarias
1. Licencia del SDK (obligatorio)
Existen dos formas de obtener la licencia del SDK:
Opción A: Solicitud Directa
- Formato: String alfanumérico único
- Ejemplo:
"ABC-123-XYZ-789" - Solicitar a: [email protected]
Opción B: Generación mediante API
Si no obtiene la licencia directamente del equipo JAAK, puede generarla mediante el siguiente proceso:
Paso 1: Obtener el Trace ID
Llamar al endpoint de inicio de flujo KYC:
POST /v1/kyc/sessionDe la respuesta, obtener el header traceparenty x-trace-id:
traceparent: 00-cf143715d7a2d4ffc3ef122f62384844-6f7048446dffdb89-00
x-trace-id :32922b9bf22570da5e9895fa592c6852
Paso 2: Validar la Licencia
Construir la licencia agregando el prefijo L al x-trace-id:
Lcf143715d7a2d4ffc3ef122f62384844
El campo obtenido se utilizará para autenticar los sdks y el campo traceparent debe de ser enviado en los headers de todos los llamados por api que se realicen .
2. Google Play Integrity API (obligatorio)
- Project Number de Google Cloud (número de 12 dígitos)
- Instrucciones de configuración
3. Permisos de Android (se configuran automáticamente)
- Permisos de Android (se configuran en AndroidManifest)
- CAMERA (obligatorio)
- WRITE_EXTERNAL_STORAGE (solo Android menor o igual a 9)
Instalacion
Paso 1: Configurar Repositorio Maven
Agregue el repositorio de JAAK en su archivo settings.gradle:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url "https://us-maven.pkg.dev/jaak-platform/jaak-android"
}
}
}Paso 2: Agregar Dependencia del SDK
En su archivo build.gradle (modulo app):
dependencies {
// JAAK Stamps SDK
implementation 'com.jaak.stampssdk:jaakstamps-sdk:1.2.3'
// Dependencias requeridas
implementation "com.google.dagger:hilt-android:2.48"
kapt "com.google.dagger:hilt-android-compiler:2.48"
}Paso 3: Configurar Plugins
En su build.gradle (modulo app):
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}Paso 4: Configurar Build.gradle del Proyecto
En su build.gradle (nivel proyecto):
buildscript {
ext.kotlin_version = "1.9.22"
ext.hilt_version = '2.48'
dependencies {
classpath 'com.android.tools.build:gradle:8.3.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
}
}Paso 5: Configurar Permisos
En su AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="tu.paquete.app">
<!-- Permisos necesarios -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"/>
<!-- Features requeridos -->
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<application
android:name=".MyApplication"
android:allowBackup="true"
...>
<!-- FileProvider para compartir archivos -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>Paso 6: Configurar FileProvider
El SDK utiliza FileProvider para compartir archivos de forma segura entre componentes. Cree el archivo res/xml/file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- For Pictures directory -->
<external-path name="my_images" path="Pictures/" />
<!-- For getExternalFilesDir() - required by Jaak Stamps SDK -->
<external-files-path name="external_files" path="." />
<external-files-path name="jaak_stamps" path="Jaak Stamps SDK/" />
<!-- For internal files and cache -->
<files-path name="internal_files" path="." />
<cache-path name="cache" path="." />
<!-- For external cache -->
<external-cache-path name="external_cache" path="." />
</paths>Configuracion Inicial
Inicializar el SDK
El SDK debe inicializarse UNA SOLA VEZ al inicio de su aplicacion:
import android.app.Application
import com.jaak.stampssdk.StampsSDK
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Inicializar el SDK con su licencia
StampsSDK.initialize("SU-LICENCIA-AQUI")
}
}No olvide registrar su Application en el AndroidManifest.xml:
<application
android:name=".MyApplication"
...>Como Usar el SDK
Arquitectura Basica
El SDK funciona mediante un patron de callbacks. Su Activity o Fragment debe:
- Implementar la interfaz
StampsListener - Crear una instancia de
StampsSDK - Configurar los parametros deseados (opcional)
- Iniciar la captura con
startStamps() - Recibir los resultados en los callbacks
Implementacion en Activity
import com.jaak.stampssdk.StampsSDK
import com.jaak.stampssdk.interfaces.StampsListener
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class MainActivity : AppCompatActivity(), StampsListener {
private lateinit var stampsSDK: StampsSDK
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Crear instancia del SDK
stampsSDK = StampsSDK(this, this)
// Configurar el SDK (opcional)
configureSDK()
// Boton para iniciar captura
findViewById<Button>(R.id.btnCapture).setOnClickListener {
startDocumentCapture()
}
}
private fun configureSDK() {
// Configuraciones opcionales
stampsSDK.apply {
setAlignmentTolerance(30)
setMaskSize(80)
setCropMargin(150)
setCaptureDelay(1500)
setShowPreview(true)
}
}
private fun startDocumentCapture() {
// Iniciar captura inteligente
// typeProcess = 1 para captura automatica inteligente
stampsSDK.startStamps(typeProcess = 1)
}
// Callbacks del SDK
override fun onSuccessStamps(
typeProcess: Int,
frontOriginalUri: Uri?,
frontCropUri: Uri?,
backOriginalUri: Uri?,
backCropUri: Uri?,
frontFaceCropUri: Uri?
) {
// Documento capturado exitosamente
handleSuccessfulCapture(
frontOriginalUri,
frontCropUri,
backOriginalUri,
backCropUri,
frontFaceCropUri
)
}
override fun onErrorStamps(error: String) {
// Error en la captura
Log.e("StampsSDK", "Error: $error")
showError(error)
}
private fun handleSuccessfulCapture(
frontOriginal: Uri?,
frontCrop: Uri?,
backOriginal: Uri?,
backCrop: Uri?,
faceCrop: Uri?
) {
// Determinar tipo de documento
val documentType = when {
backOriginal != null -> "INE/IFE (frente y reverso)"
frontOriginal != null -> "Pasaporte (solo frente)"
else -> "Desconocido"
}
Log.d("StampsSDK", "Tipo de documento: $documentType")
// Procesar imagenes
processDocument(frontCrop, backCrop, faceCrop)
}
}Parametros de Entrada
1. initialize(license: String)
Inicializa el SDK con la licencia proporcionada por JAAK.
Tipo: String
Descripcion:
- Debe llamarse UNA SOLA VEZ al inicio de la aplicacion
- Generalmente se llama en la clase Application
- La licencia valida que la app tiene permiso para usar el SDK
- Sin una licencia valida, el SDK no funcionara
Parametro license:
- Formato: String alfanumerico con guiones
- Ejemplo: "ABCD-1234-EFGH-5678"
- Longitud tipica: 19 caracteres
- Sensible a mayusculas/minusculas
Ejemplo:
@HiltAndroidApp
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
StampsSDK.initialize("ABCD-1234-EFGH-5678")
}
}Como obtener licencia:
- Enviar email a: [email protected]
- Proporcionar: nombre de empresa, package name de app
- Licencias de desarrollo son gratuitas
- Licencias de produccion tienen costo segun volumen
Importante:
- NO incluir la licencia directamente en el codigo versionado
- Usar BuildConfig o archivo de configuracion:
// En build.gradle
buildConfigField("String", "STAMPS_LICENSE", "\"${project.findProperty("stamps.license")}\"")
// En local.properties
stamps.license=ABCD-1234-EFGH-5678
// En codigo
StampsSDK.initialize(BuildConfig.STAMPS_LICENSE)2. StampsSDK(activity: AppCompatActivity, listener: StampsListener)
Constructor que crea una instancia del SDK para una Activity especifica.
Parametros:
| Parametro | Tipo | Obligatorio | Descripcion |
|---|---|---|---|
| activity | AppCompatActivity | Si | Activity desde donde se inicia el SDK |
| listener | StampsListener | Si | Interfaz para recibir callbacks |
Descripcion:
Parametro activity:
- La Activity debe estar anotada con @AndroidEntryPoint si usa Hilt
- El SDK necesita el contexto de la Activity para:
- Solicitar permisos de camara
- Iniciar la Activity de captura
- Gestionar el ciclo de vida
- Debe ser la Activity desde donde se llama startStamps()
Parametro listener:
- Debe ser una clase que implemente StampsListener
- Generalmente la misma Activity implementa esta interfaz
- Recibe los callbacks con resultados y errores
Ejemplo:
@AndroidEntryPoint
class CaptureActivity : AppCompatActivity(), StampsListener {
private lateinit var stampsSDK: StampsSDK
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Crear instancia pasando this como Activity y Listener
stampsSDK = StampsSDK(
activity = this, // Esta Activity
listener = this // Esta Activity implementa StampsListener
)
}
override fun onSuccessStamps(...) { }
override fun onErrorStamps(error: String) { }
}Ciclo de vida:
- Cada Activity debe tener su propia instancia de StampsSDK
- El SDK gestiona automaticamente los cambios de configuracion
- No es necesario liberar recursos manualmente
3. startStamps(typeProcess: Int)
Inicia el proceso de captura de documentos.
Tipo: Int
Valores posibles:
| Valor | Nombre | Descripcion | Cuando usar |
|---|---|---|---|
| 1 | Captura Inteligente | El SDK detecta automaticamente el tipo de documento y captura frente y/o reverso segun sea necesario | Recomendado - La mayoria de casos |
| 2 | Solo Frente | Captura unicamente el frente del documento | Cuando sabes que es pasaporte o documento sin reverso |
| 3 | Frente y Reverso | Captura obligatoriamente frente y reverso | Cuando sabes que es INE/IFE/Cedula |
Valor por defecto: No tiene valor por defecto, debe especificarse
Descripcion detallada:
typeProcess = 1 (Captura Inteligente) - RECOMENDADO
El modo mas comun e inteligente:
- El SDK analiza el documento capturado
- Determina automaticamente si tiene reverso
- Para documentos con reverso (INE, IFE):
- Captura el frente
- Automaticamente pide capturar el reverso
- Retorna ambas imagenes
- Para documentos sin reverso (Pasaporte):
- Captura solo el frente
- Retorna solo imagenes del frente
- backOriginalUri y backCropUri seran null
Ventajas:
- No necesitas saber que tipo de documento es
- Experiencia de usuario mas fluida
- Reduce errores (no pide reverso de pasaportes)
Desventajas:
- Ninguna significativa
typeProcess = 2 (Solo Frente)
Captura unicamente el frente del documento:
- Solo hace una captura
- No pide el reverso aunque el documento lo tenga
- Util cuando solo necesitas la foto del documento
Cuando usar:
- Sabes con certeza que es un pasaporte
- Solo necesitas la foto del frente para validacion rapida
- Registro simplificado donde no necesitas datos del reverso
- Casos donde el reverso no agrega valor
Retorna:
- frontOriginalUri - Foto completa del frente
- frontCropUri - Documento recortado
- frontFaceCropUri - Rostro extraido (si disponible)
- backOriginalUri - Siempre null
- backCropUri - Siempre null
typeProcess = 3 (Frente y Reverso)
Captura obligatoriamente frente y reverso:
- Siempre pide dos capturas
- Incluso si es un pasaporte (que no tiene reverso)
- Util cuando SABES que necesitas ambos lados
Cuando usar:
- Estas 100% seguro que es INE/IFE/Cedula
- Tu proceso REQUIERE ambos lados siempre
- Validacion completa de documentos con reverso
Retorna:
- frontOriginalUri - Foto completa del frente
- frontCropUri - Documento recortado (frente)
- backOriginalUri - Foto completa del reverso
- backCropUri - Documento recortado (reverso)
- frontFaceCropUri - Rostro extraido (si disponible)
Ejemplo:
// Modo recomendado - Captura inteligente
stampsSDK.startStamps(1) // Mejor para la mayoria de casos
// Solo frente - para pasaportes o registro rapido
stampsSDK.startStamps(2) // Cuando solo necesitas el frente
// Frente y reverso obligatorio - para INE/IFE
stampsSDK.startStamps(3) // Cuando necesitas ambos ladosCual usar:
| Tu caso de uso | typeProcess recomendado |
|---|---|
| No sabes que documento subira el usuario | 1 (Inteligente) |
| Onboarding general de usuarios | 1 (Inteligente) |
| Verificacion KYC completa | 1 (Inteligente) |
| Solo aceptas pasaportes | 2 (Solo frente) |
| Registro rapido sin validacion exhaustiva | 2 (Solo frente) |
| Solo aceptas INE/IFE mexicana | 3 (Frente y reverso) |
| Necesitas datos del reverso siempre | 3 (Frente y reverso) |
4. setAlignmentTolerance(tolerance: Int)
Configura que tan estricto es el SDK al validar la alineacion del documento.
Tipo: Int
Rango valido: 0 - 100
Valor por defecto: 30
Descripcion:
Este parametro controla que tan perfectamente alineado debe estar el documento para ser capturado:
-
Valor bajo (0-20):
- Muy estricto
- Requiere alineacion casi perfecta
- Mejor calidad de imagen
- Usuario tarda mas en capturar
- Recomendado para: aplicaciones financieras, KYC regulado
-
Valor medio (20-40):
- Balance entre calidad y facilidad
- Alineacion razonable requerida
- Buena calidad de imagen
- Tiempo de captura moderado
- Recomendado para: la mayoria de aplicaciones
-
Valor alto (40-100):
- Muy tolerante
- Acepta documentos con ligera inclinacion
- Captura mas rapida
- Calidad puede variar mas
- Recomendado para: dispositivos de gama baja, usuarios con dificultades motoras
Ejemplo:
// Maxima calidad (fintech, bancos)
stampsSDK.setAlignmentTolerance(15)
// Balance calidad/facilidad (recomendado)
stampsSDK.setAlignmentTolerance(30)
// Facilidad de uso (apps masivas)
stampsSDK.setAlignmentTolerance(45)
// Muy permisivo (gama baja)
stampsSDK.setAlignmentTolerance(60)5. setMaskSize(size: Int)
Configura el tamano del area de deteccion del documento en pantalla.
Tipo: Int
Rango valido: 50 - 100
Valor por defecto: 80
Descripcion:
Este parametro define que tan grande es el marco/mascara que aparece en pantalla para guiar al usuario:
-
Valor bajo (50-65):
- Marco pequeno en pantalla
- Usuario debe acercar mas la camara
- Mejor para pantallas pequenas
- Mas procesamiento (area menor)
- Recomendado para: dispositivos de gama baja, pantallas menores a 5"
-
Valor medio (65-85):
- Marco de tamano moderado
- Balance entre facilidad y rendimiento
- Comodo para la mayoria de usuarios
- Recomendado para: la mayoria de aplicaciones
-
Valor alto (85-100):
- Marco grande en pantalla
- Usuario puede estar mas alejado
- Mas facil de usar
- Requiere mas procesamiento
- Recomendado para: tablets, pantallas mayores a 6", usuarios con dificultades visuales
Impacto en la experiencia:
| Tamano del Marco | Distancia optima | Dificultad | Rendimiento |
|---|---|---|---|
| 50-65 (pequeno) | 15-20 cm | Alta | Excelente |
| 65-80 (medio) | 20-30 cm | Media | Bueno |
| 80-95 (grande) | 30-40 cm | Baja | Moderado |
| 95-100 (muy grande) | 40+ cm | Muy baja | Puede ser lento en gama baja |
Ejemplo:
// Pantalla pequena / gama baja
stampsSDK.setMaskSize(65)
// Tamano estandar (recomendado)
stampsSDK.setMaskSize(80)
// Pantalla grande / facilidad maxima
stampsSDK.setMaskSize(90)Recomendacion por tipo de dispositivo:
| Tipo de dispositivo | Valor recomendado |
|---|---|
| Gama baja (menor a 2GB RAM) | 60-70 |
| Gama media (2-4GB RAM) | 75-85 |
| Gama alta (mayor a 4GB RAM) | 80-95 |
| Tablets | 85-95 |
6. setCropMargin(margin: Int)
Configura el margen adicional que se incluye al recortar el documento.
Tipo: Int
Rango valido: 0 - 170
Valor por defecto: 150
Descripcion:
Este parametro controla cuanto contexto adicional se incluye alrededor del documento en la imagen recortada:
-
Valor bajo (0-100):
- Recorte muy ajustado al documento
- Imagen mas pequena (menos MB)
- Puede cortar bordes si la deteccion no es perfecta
- Riesgo de perder informacion de los bordes
- Recomendado solo si el espacio es critico
-
Valor medio (100-160):
- Balance entre precision y contexto
- Incluye bordes completos del documento
- Tamano de archivo razonable
- Seguro para procesamiento OCR
- Recomendado para: la mayoria de aplicaciones
-
Valor alto (160-170):
- Incluye mucho contexto alrededor
- Garantiza captura de todos los bordes
- Archivos mas grandes
- Util para validacion visual manual
- Recomendado para: aplicaciones de archivo documental
Ejemplo:
// Recorte ajustado (ahorro de espacio)
stampsSDK.setCropMargin(100)
// Recorte estandar (recomendado)
stampsSDK.setCropMargin(150)
// Recorte amplio (archivo documental)
stampsSDK.setCropMargin(170)Recomendacion por caso de uso:
| Caso de uso | Valor recomendado | Justificacion |
|---|---|---|
| OCR automatico | 130-150 | Garantiza captura de todos los campos |
| Validacion visual | 150-170 | Incluye contexto para revision humana |
| Almacenamiento limitado | 100-120 | Reduce tamano de archivos |
| Archivo legal | 160-170 | Maximo contexto para evidencia |
| Procesamiento AI | 140-160 | Balance entre contexto y tamano |
7. setCaptureDelay(milliseconds: Int)
Configura el tiempo de espera antes de capturar automaticamente.
Tipo: Int (milisegundos)
Rango valido: 500 - 5000
Valor por defecto: 1500 (1.5 segundos)
Descripcion:
Este parametro define cuanto tiempo debe mantener el usuario el documento correctamente posicionado antes de que el SDK capture automaticamente:
-
Valor bajo (500-1000ms):
- Captura muy rapida
- Menos tiempo de espera para el usuario
- Mayor riesgo de capturar imagen borrosa (movimiento)
- Recomendado para: usuarios expertos, dispositivos de gama alta
-
Valor medio (1000-2000ms):
- Balance entre velocidad y estabilidad
- Tiempo suficiente para estabilizar
- Experiencia fluida
- Recomendado para: la mayoria de aplicaciones
-
Valor alto (2000-5000ms):
- Captura muy estable
- Usuario tiene mucho tiempo para posicionar
- Puede sentirse lento
- Garantiza mejor calidad
- Recomendado para: gama baja, usuarios con dificultades motoras
Impacto en la experiencia:
| Delay | Experiencia del usuario | Calidad esperada | Mejor para |
|---|---|---|---|
| 500-800ms | Muy rapida, puede sorprender | Variable | Usuarios expertos |
| 1000-1500ms | Fluida y natural | Buena | Usuarios generales |
| 1500-2500ms | Comoda, no apurada | Muy buena | Primera vez usuarios |
| 2500-5000ms | Lenta, puede frustrar | Excelente | Casos especiales |
Ejemplo:
// Captura rapida (usuarios expertos)
stampsSDK.setCaptureDelay(1000)
// Captura estandar (recomendado)
stampsSDK.setCaptureDelay(1500)
// Captura con pausa (maxima estabilidad)
stampsSDK.setCaptureDelay(2500)Recomendacion por contexto:
| Contexto | Valor recomendado | Justificacion |
|---|---|---|
| Primera captura del usuario | 2000-2500ms | Dale tiempo para entender |
| Usuario experimentado | 1000-1500ms | Ya sabe que hacer |
| Dispositivo de gama alta | 1000-1500ms | Procesa rapido y estable |
| Dispositivo de gama baja | 1500-2000ms | Necesita mas tiempo para procesar |
| Entorno con movimiento | 2000-3000ms | Esperar momento de estabilidad |
| Punto de venta rapido | 1000-1200ms | Velocidad es prioridad |
Combinacion con otros parametros:
// Configuracion RAPIDA (punto de venta)
stampsSDK.apply {
setCaptureDelay(1000) // Captura rapida
setAlignmentTolerance(40) // Mas tolerante
setShowPreview(false) // Sin preview, mas directo
}
// Configuracion PRECISA (banca/finanzas)
stampsSDK.apply {
setCaptureDelay(2000) // Captura estable
setAlignmentTolerance(20) // Muy estricto
setShowPreview(true) // Permitir revision
}
// Configuracion BALANCED (recomendada)
stampsSDK.apply {
setCaptureDelay(1500) // Balance
setAlignmentTolerance(30) // Balance
setShowPreview(true) // Incluir preview
}8. setShowPreview(enabled: Boolean)
Configura si se muestra una pantalla de vista previa despues de cada captura.
Tipo: Boolean
Valores posibles:
- true - Muestra preview, usuario puede aceptar o reintentar
- false - Sin preview, captura directa
Valor por defecto: true
Descripcion:
Este parametro controla el flujo de experiencia del usuario despues de cada captura:
Cuando enabled = true (Con Preview) - RECOMENDADO
Despues de capturar cada imagen:
- SDK muestra la imagen capturada en pantalla
- Usuario ve dos botones:
- Aceptar/Continuar - Confirma que la imagen es buena
- Reintentar - Vuelve a capturar si no esta satisfecho
- Si aceptan: continua al siguiente paso o termina
- Si reintenta: vuelve a la camara para nueva captura
Ventajas:
- Usuario tiene control y confianza
- Puede corregir capturas borrosas o mal iluminadas
- Reduce reintentos completos del proceso
- Mejor experiencia de usuario
Desventajas:
- Proceso un poco mas largo
- Requiere un tap adicional por captura
Cuando usar:
- Verificacion de identidad (KYC)
- Onboarding de usuarios
- Aplicaciones donde la calidad es critica
- Primera vez que el usuario usa la app
- Cuando el usuario es el dueno del documento
Cuando enabled = false (Sin Preview) - FLUJO RAPIDO
Despues de capturar cada imagen:
- SDK captura y procesa automaticamente
- No muestra la imagen al usuario
- Pasa directamente al siguiente paso o termina
- Proceso completamente automatico
Ventajas:
- Proceso muy rapido
- Menos interacciones requeridas
- Ideal para alto volumen de capturas
- Experiencia mas fluida
Desventajas:
- Usuario no puede validar calidad antes de enviar
- Si la imagen es mala, debe repetir todo el proceso
- Menos control para el usuario
Cuando usar:
- Puntos de venta rapidos
- Procesos donde un operador captura (no el dueno del documento)
- Alto volumen de transacciones
- Cuando el tiempo es critico
- Usuarios expertos que repiten el proceso frecuentemente
Ejemplo:
// Con preview (recomendado para la mayoria)
stampsSDK.setShowPreview(true)
// Sin preview (flujo rapido)
stampsSDK.setShowPreview(false)Comparacion de flujos:
CON PREVIEW (true):
1. Usuario posiciona documento
2. SDK captura automaticamente
3. [PANTALLA DE PREVIEW]
4. Usuario ve la imagen
5. Usuario decide: Aceptar o Reintentar?
- Aceptar -> Continuar
- Reintentar -> Volver a paso 1
SIN PREVIEW (false):
1. Usuario posiciona documento
2. SDK captura automaticamente
3. Procesa y continua inmediatamente
9. setShowDebugMode(enabled: Boolean)
Activa o desactiva el modo de depuracion con logs detallados.
Tipo: Boolean
Valores posibles:
- true - Activa logs detallados en Logcat
- false - Logs minimos (solo errores)
Valor por defecto: false
Descripcion:
Cuando esta activado, el SDK genera logs detallados sobre:
- Inicializacion del SDK
- Validacion de licencia
- Proceso de captura (deteccion, alineacion, calidad)
- Recorte de imagenes
- Extraccion de rostro
- Guardado de archivos
- Errores y warnings
Cuando activarlo:
- Durante desarrollo
- Al integrar el SDK por primera vez
- Al debuggear problemas
- Cuando contactes a soporte tecnico
- NO en produccion (impacto en rendimiento)
Ejemplo:
// Activar en desarrollo
if (BuildConfig.DEBUG) {
stampsSDK.setShowDebugMode(true)
}
// Desactivar en produccion
if (!BuildConfig.DEBUG) {
stampsSDK.setShowDebugMode(false)
}Logs tipicos que veras:
D/StampsSDK: Initializing SDK with license: XXXX-****-****-XXXX
D/StampsSDK: License validated successfully
D/StampsSDK: Starting capture with typeProcess: 1
D/StampsSDK: Document detected in frame
D/StampsSDK: Alignment: 85% (tolerance: 30%)
D/StampsSDK: Quality check: brightness=OK, sharpness=OK, size=OK
D/StampsSDK: Auto-capture in 1500ms
D/StampsSDK: Image captured successfully
D/StampsSDK: Cropping document with margin: 150
D/StampsSDK: Extracting face from document
D/StampsSDK: Face detected and extracted
D/StampsSDK: Analyzing document type: INE detected
D/StampsSDK: Requesting back side capture
D/StampsSDK: Process completed successfully
Importante:
- Los logs pueden contener informacion sensible
- No dejar activado en produccion
- Revisar logs antes de enviar a soporte (remover datos sensibles)
10. setSecurityValidationEnabled(enabled: Boolean)
Activa validaciones de seguridad adicionales contra emuladores y camaras virtuales.
Tipo: Boolean
Valores posibles:
- true - Activa validaciones de seguridad
- false - Sin validaciones adicionales
Valor por defecto: false
Descripcion:
Cuando esta activado, el SDK realiza validaciones adicionales para:
- Detectar si esta corriendo en un emulador
- Verificar si la camara es virtual/simulada
- Validar que el dispositivo es autentico
- Prevenir ataques de spoofing basicos
Cuando activarlo:
| Industria | Recomendacion | Justificacion |
|---|---|---|
| Banca/Finanzas | Activar | Alto riesgo de fraude |
| Seguros | Activar | Validacion critica |
| Fintech | Activar | Regulaciones KYC |
| E-commerce | Considerar | Segun nivel de riesgo |
| Apps de Delivery | No necesario | Bajo riesgo de fraude |
| Registro general | No necesario | Validacion basica suficiente |
Impacto:
- Mayor seguridad
- Previene fraudes basicos
- Puede rechazar algunos dispositivos legitimos en casos edge
- Ligero impacto en rendimiento
Ejemplo:
// Para aplicaciones financieras
stampsSDK.setSecurityValidationEnabled(true)
// Para aplicaciones de uso general
stampsSDK.setSecurityValidationEnabled(false)Validaciones que realiza:
-
Deteccion de emulador:
- Verifica propiedades del dispositivo
- Detecta emuladores comunes (Android Studio, Genymotion, etc.)
-
Validacion de camara:
- Verifica que la camara sea hardware real
- Detecta camaras virtuales o simuladas
-
Integridad del dispositivo:
- Valida que el dispositivo no esta rooteado (opcional)
- Verifica firma de la aplicacion
Que pasa si detecta problema:
- El callback onErrorStamps() se invoca
- Error tipo: "security_validation_failed"
- Mensaje descriptivo del problema detectado
Importante:
- No es una solucion de seguridad completa
- Para maxima seguridad, validar tambien en tu backend
- Complementar con otras medidas de seguridad
- Puede generar falsos positivos en dispositivos modificados legitimamente
Parametros de Salida
Interface: StampsListener
Su Activity o Fragment debe implementar esta interfaz para recibir los resultados del SDK.
interface StampsListener {
fun onSuccessStamps(
typeProcess: Int,
frontOriginalUri: Uri?,
frontCropUri: Uri?,
backOriginalUri: Uri?,
backCropUri: Uri?,
frontFaceCropUri: Uri?
)
fun onErrorStamps(error: String)
}1. onSuccessStamps(...) - Callback de Exito
Se invoca cuando el SDK completa exitosamente la captura del documento.
Cuando se invoca:
- Despues de capturar todas las imagenes requeridas (frente y/o reverso)
- Despues de que el usuario confirme en el preview (si esta activado)
- Cuando todas las imagenes han sido procesadas y guardadas
Parametros:
typeProcess: Int
Devuelve el mismo valor de typeProcess que se paso a startStamps().
Tipo: Int
Valores posibles: 1, 2, o 3
Uso: Permite identificar que modo de captura se uso, util si manejas multiples flujos.
Ejemplo:
override fun onSuccessStamps(
typeProcess: Int,
...
) {
when (typeProcess) {
1 -> Log.d("Stamps", "Captura inteligente completada")
2 -> Log.d("Stamps", "Solo frente capturado")
3 -> Log.d("Stamps", "Frente y reverso capturados")
}
}frontOriginalUri: Uri?
URI de la imagen original del frente del documento (sin recortar).
Tipo: Uri? (puede ser null)
Cuando es null:
- Nunca deberia ser null si el callback se ejecuta exitosamente
- Si es null, hubo un error en el guardado del archivo
Descripcion:
- Imagen completa tal como fue capturada por la camara
- Incluye todo el encuadre: documento + fondo
- Resolucion completa de la camara
- Sin procesamiento ni recortes
- Util para auditoria o validacion manual
Caracteristicas tipicas:
- Formato: JPEG
- Resolucion: Segun camara del dispositivo (tipicamente 2-12 MP)
- Tamano de archivo: 1-5 MB
- Ubicacion: Almacenamiento interno de la app
Cuando usar esta imagen:
- Archivo documental completo
- Necesitas contexto alrededor del documento
- Validacion manual humana
- Backup/auditoria
- Cuando la calidad del recorte no es optima
Ejemplo:
override fun onSuccessStamps(..., frontOriginalUri: Uri?, ...) {
frontOriginalUri?.let { uri ->
// Guardar para auditoria
saveToBackup(uri)
// Mostrar en ImageView
binding.imageOriginal.setImageURI(uri)
// Convertir a Base64
val base64 = Utils.uriToBase64(contentResolver, uri)
}
}frontCropUri: Uri?
URI de la imagen del frente del documento recortada y optimizada.
Tipo: Uri? (puede ser null)
Cuando es null:
- Solo si hubo error en el proceso de recorte
- Muy raro, generalmente siempre esta presente
Descripcion:
- Documento recortado eliminando el fondo
- Solo contiene el documento y un margen configurable
- Optimizada para procesamiento (OCR, validacion)
- Mejor calidad visual
- Esta es la imagen que DEBES usar para procesamiento
Caracteristicas tipicas:
- Formato: JPEG
- Resolucion: Optimizada (tipicamente 1200-2000px de ancho)
- Tamano de archivo: 200-800 KB
- Orientacion: Siempre horizontal (el SDK rota automaticamente)
- Ubicacion: Almacenamiento interno de la app
Procesamiento aplicado:
- Recorte inteligente del documento
- Correccion de perspectiva (si estaba inclinado)
- Mejora de contraste
- Reduccion de ruido
- Rotacion a orientacion correcta
Cuando usar esta imagen:
- OCR (extraccion de datos)
- Validacion automatica del documento
- Envio a APIs de verificacion
- Machine Learning / IA
- Comparacion con base de datos
- Procesamiento en general
Ejemplo:
override fun onSuccessStamps(..., frontCropUri: Uri?, ...) {
frontCropUri?.let { uri ->
// Convertir a Base64 para API
val base64 = Utils.uriToBase64(contentResolver, uri)
// Enviar a servicio de OCR
ocrService.extractData(base64)
// Enviar a API de validacion
apiService.validateDocument(base64)
// Mostrar en UI
binding.imageDocument.setImageURI(uri)
}
}backOriginalUri: Uri?
URI de la imagen original del reverso del documento (sin recortar).
Tipo: Uri? (puede ser null)
Cuando es null:
- Cuando el documento NO tiene reverso (ej: Pasaporte)
- Cuando se uso startStamps(2) (solo frente)
- En captura inteligente, si detecto que es documento sin reverso
Cuando tiene valor:
- Cuando el documento tiene reverso (INE, IFE, Cedula)
- Cuando se uso startStamps(3) (frente y reverso obligatorio)
- En captura inteligente, si detecto documento con reverso
Descripcion:
- Imagen completa del reverso tal como fue capturada
- Incluye documento + fondo
- Resolucion completa de la camara
- Sin procesamiento ni recortes
Uso: Similar a frontOriginalUri pero para el reverso
Ejemplo:
override fun onSuccessStamps(
...,
backOriginalUri: Uri?,
...
) {
if (backOriginalUri != null) {
// Documento tiene reverso (INE/IFE/Cedula)
Log.d("Stamps", "Documento con reverso capturado")
saveBackOriginal(backOriginalUri)
} else {
// Documento sin reverso (Pasaporte) o solo capturo frente
Log.d("Stamps", "Documento sin reverso o solo frente capturado")
}
}backCropUri: Uri?
URI de la imagen del reverso del documento recortada y optimizada.
Tipo: Uri? (puede ser null)
Cuando es null:
- Cuando el documento NO tiene reverso (ej: Pasaporte)
- Cuando se uso startStamps(2) (solo frente)
- En captura inteligente, si detecto que es documento sin reverso
Cuando tiene valor:
- Cuando el documento tiene reverso
- Cuando se capturaron ambos lados
Descripcion:
- Reverso del documento recortado y optimizado
- Solo contiene el documento con margen configurable
- Procesamiento identico a frontCropUri
- Usar esta imagen para procesar datos del reverso
Uso: Similar a frontCropUri pero para el reverso
Datos comunes en el reverso:
- INE/IFE: Domicilio, CURP, CIC, fecha de registro, codigo de barras
- Licencia: Restricciones, tipo de licencia, vigencia
- Cedula: Informacion adicional segun el pais
Ejemplo:
override fun onSuccessStamps(
...,
backCropUri: Uri?,
...
) {
backCropUri?.let { uri ->
// Convertir a Base64
val base64Back = Utils.uriToBase64(contentResolver, uri)
// Extraer datos del reverso
ocrService.extractBackData(base64Back) // CURP, domicilio, etc.
// Validar codigo de barras/QR si existe
barcodeService.validateQRCode(base64Back)
}
}frontFaceCropUri: Uri?
URI de la foto del rostro extraida automaticamente del frente del documento.
Tipo: Uri? (puede ser null)
Cuando es null:
- Cuando el documento NO contiene foto (raro, la mayoria tienen)
- Cuando el SDK no pudo detectar/extraer el rostro
- En documentos muy antiguos o deteriorados
- Si la foto en el documento esta muy borrosa
Cuando tiene valor:
- Cuando el documento tiene foto del titular (mayoria de casos)
- INE, IFE, Pasaportes, Licencias, Cedulas
Descripcion:
- Foto del rostro extraida automaticamente del documento
- Recortada precisamente alrededor del rostro
- Optimizada para comparacion facial (face matching)
- Sin fondo ni elementos del documento
- Resolucion adecuada para procesamiento biometrico
Caracteristicas tipicas:
- Formato: JPEG
- Resolucion: 200x250 px aproximadamente (varia segun documento)
- Tamano de archivo: 10-50 KB
- Solo contiene el rostro
- Puede incluir parte del fondo de la foto original del documento
Cuando usar esta imagen:
- Comparacion facial (face matching) con selfie
- Verificacion biometrica
- Validacion de identidad
- Sistemas de reconocimiento facial
- Analisis de liveness (prueba de vida)
- Onboarding con verificacion facial
Ejemplo de uso completo:
override fun onSuccessStamps(
typeProcess: Int,
frontOriginalUri: Uri?,
frontCropUri: Uri?,
backOriginalUri: Uri?,
backCropUri: Uri?,
frontFaceCropUri: Uri?
) {
// 1. Validar que tenemos las imagenes necesarias
if (frontCropUri == null) {
showError("No se pudo capturar el frente del documento")
return
}
// 2. Determinar tipo de documento
val documentType = when {
backCropUri != null -> "INE/IFE"
frontCropUri != null && backCropUri == null -> "Pasaporte"
else -> "Desconocido"
}
Log.d("Stamps", "Tipo de documento: $documentType")
// 3. Procesar imagen del frente (OCR)
val frontBase64 = Utils.uriToBase64(contentResolver, frontCropUri)
extractFrontData(frontBase64)
// 4. Procesar reverso si existe
backCropUri?.let { uri ->
val backBase64 = Utils.uriToBase64(contentResolver, uri)
extractBackData(backBase64)
}
// 5. Procesar rostro si existe
frontFaceCropUri?.let { uri ->
val faceBase64 = Utils.uriToBase64(contentResolver, uri)
// Guardar para comparacion posterior con selfie
saveFaceForComparison(faceBase64)
// O hacer comparacion inmediata si ya tienes selfie
val selfieBase64 = getUserSelfie()
if (selfieBase64 != null) {
compareFaces(faceBase64, selfieBase64)
}
} ?: run {
Log.w("Stamps", "No se pudo extraer rostro del documento")
// Continuar sin comparacion facial o pedir selfie manual
}
// 6. Guardar todo para auditoria
saveDocumentCapture(
frontOriginal = frontOriginalUri,
frontCrop = frontCropUri,
backOriginal = backOriginalUri,
backCrop = backCropUri,
face = frontFaceCropUri,
documentType = documentType,
timestamp = System.currentTimeMillis()
)
// 7. Continuar con el flujo
navigateToNextStep()
}
private fun extractFrontData(base64: String) {
// Extraer: nombre, apellidos, fecha nacimiento, etc.
ocrService.extractFrontData(base64) { data ->
// Procesar datos extraidos
Log.d("OCR", "Nombre: ${data.name}")
Log.d("OCR", "Fecha nacimiento: ${data.birthDate}")
}
}
private fun extractBackData(base64: String) {
// Extraer: CURP, domicilio, CIC, etc.
ocrService.extractBackData(base64) { data ->
Log.d("OCR", "CURP: ${data.curp}")
Log.d("OCR", "Domicilio: ${data.address}")
}
}
private fun compareFaces(documentFace: String, selfieFace: String) {
faceMatchService.compare(documentFace, selfieFace) { result ->
if (result.isMatch && result.confidence > 0.85) {
Log.d("FaceMatch", "Rostros coinciden: ${result.confidence}")
approveIdentityVerification()
} else {
Log.w("FaceMatch", "Rostros no coinciden: ${result.confidence}")
requestManualReview()
}
}
}Resumen de imagenes recibidas:
| URI | Contiene | Cuando es null | Usar para |
|---|---|---|---|
| frontOriginalUri | Frente completo sin recortar | Nunca | Auditoria, backup |
| frontCropUri | Frente recortado y optimizado | Nunca | OCR, validacion, procesamiento |
| backOriginalUri | Reverso completo sin recortar | Si no tiene reverso | Auditoria, backup |
| backCropUri | Reverso recortado y optimizado | Si no tiene reverso | OCR reverso, datos adicionales |
| frontFaceCropUri | Rostro extraido | Si no tiene foto o no se detecto | Face matching, biometria |
2. onErrorStamps(error: String) - Callback de Error
Se invoca cuando ocurre un error durante el proceso de captura.
Cuando se invoca:
- Error al inicializar la camara
- Permisos de camara denegados
- Error al guardar las imagenes
- Licencia invalida
- Error de procesamiento
- Usuario cancela el proceso (en algunas implementaciones)
Parametro error:
Tipo: String
Descripcion: Mensaje descriptivo del error que ocurrio
Errores comunes:
| Mensaje de Error | Causa | Solucion |
|---|---|---|
| "Camera permission denied" | Usuario denego permiso de camara | Solicitar permiso nuevamente, explicar por que es necesario |
| "Camera not available" | Camara en uso o no existe | Verificar que el dispositivo tenga camara, cerrar otras apps que la usen |
| "License invalid" | Licencia incorrecta o expirada | Verificar licencia, contactar [email protected] |
| "Failed to save image" | Error al guardar archivo | Verificar espacio de almacenamiento, permisos de escritura |
| "Document detection failed" | No se pudo detectar documento en timeout | Mejorar iluminacion, usar fondo contrastante |
| "Image processing error" | Error al procesar/recortar imagen | Reintentar captura, puede ser problema temporal |
| "Security validation failed" | Dispositivo no paso validaciones de seguridad | Dispositivo puede ser emulador o tener camara virtual |
| "User cancelled" | Usuario cancelo el proceso | Normal, permitir reintentar |
| "Low memory" | Dispositivo sin memoria suficiente | Cerrar apps en background, liberar memoria |
| "Network error" | Error de red (si SDK requiere internet) | Verificar conectividad |
Ejemplo de manejo completo:
override fun onErrorStamps(error: String) {
Log.e("StampsSDK", "Error: $error")
when {
error.contains("permission", ignoreCase = true) -> {
// Error de permisos
handlePermissionError()
}
error.contains("camera not available", ignoreCase = true) -> {
// Camara no disponible
handleCameraUnavailable()
}
error.contains("license", ignoreCase = true) -> {
// Problema con licencia
handleLicenseError()
}
error.contains("failed to save", ignoreCase = true) -> {
// Error al guardar
handleSaveError()
}
error.contains("cancelled", ignoreCase = true) -> {
// Usuario cancelo
handleUserCancellation()
}
error.contains("security", ignoreCase = true) -> {
// Problema de seguridad
handleSecurityError()
}
error.contains("memory", ignoreCase = true) -> {
// Memoria baja
handleLowMemory()
}
else -> {
// Error generico
handleGenericError(error)
}
}
}
private fun handlePermissionError() {
AlertDialog.Builder(this)
.setTitle("Permiso necesario")
.setMessage("Necesitamos acceso a la camara para capturar tu documento de identidad.")
.setPositiveButton("Permitir") { _, _ ->
requestCameraPermission()
}
.setNegativeButton("Cancelar") { dialog, _ ->
dialog.dismiss()
finish()
}
.show()
}
private fun handleCameraUnavailable() {
AlertDialog.Builder(this)
.setTitle("Camara no disponible")
.setMessage("No pudimos acceder a la camara. Asegurate de que ninguna otra aplicacion la este usando.")
.setPositiveButton("Reintentar") { _, _ ->
stampsSDK.startStamps(1)
}
.setNegativeButton("Cancelar") { dialog, _ ->
dialog.dismiss()
}
.show()
}
private fun handleLicenseError() {
AlertDialog.Builder(this)
.setTitle("Error de configuracion")
.setMessage("Hubo un problema con la configuracion de la aplicacion. Por favor contacta a soporte.")
.setPositiveButton("Entendido") { dialog, _ ->
dialog.dismiss()
// Registrar error para analisis
logCriticalError("License validation failed")
// Opcionalmente cerrar la app
finish()
}
.setCancelable(false)
.show()
}
private fun handleSaveError() {
AlertDialog.Builder(this)
.setTitle("Error al guardar")
.setMessage("No pudimos guardar las imagenes capturadas. Verifica que tengas espacio disponible.")
.setPositiveButton("Reintentar") { _, _ ->
stampsSDK.startStamps(1)
}
.setNegativeButton("Cancelar") { dialog, _ ->
dialog.dismiss()
}
.show()
}
private fun handleUserCancellation() {
// Usuario cancelo, comportamiento normal
AlertDialog.Builder(this)
.setTitle("Captura cancelada")
.setMessage("Deseas intentar nuevamente?")
.setPositiveButton("Si") { _, _ ->
stampsSDK.startStamps(1)
}
.setNegativeButton("No") { dialog, _ ->
dialog.dismiss()
finish()
}
.show()
}
private fun handleSecurityError() {
AlertDialog.Builder(this)
.setTitle("Validacion de seguridad fallida")
.setMessage("Tu dispositivo no paso las validaciones de seguridad. Esto puede ocurrir en emuladores o dispositivos modificados.")
.setPositiveButton("Entendido") { dialog, _ ->
dialog.dismiss()
finish()
}
.setCancelable(false)
.show()
}
private fun handleLowMemory() {
AlertDialog.Builder(this)
.setTitle("Memoria insuficiente")
.setMessage("Tu dispositivo tiene poca memoria disponible. Cierra otras aplicaciones e intenta nuevamente.")
.setPositiveButton("Reintentar") { _, _ ->
// Sugerir liberar memoria
System.gc()
stampsSDK.startStamps(1)
}
.setNegativeButton("Cancelar") { dialog, _ ->
dialog.dismiss()
}
.show()
}
private fun handleGenericError(error: String) {
AlertDialog.Builder(this)
.setTitle("Error")
.setMessage("Ocurrio un error: $error\n\nDeseas intentar nuevamente?")
.setPositiveButton("Reintentar") { _, _ ->
stampsSDK.startStamps(1)
}
.setNegativeButton("Cancelar") { dialog, _ ->
dialog.dismiss()
}
.show()
}Ejemplos de Uso
Ejemplo 1: Implementacion Basica (Captura Inteligente)
@AndroidEntryPoint
class DocumentCaptureActivity : AppCompatActivity(), StampsListener {
private lateinit var stampsSDK: StampsSDK
private lateinit var binding: ActivityDocumentCaptureBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDocumentCaptureBinding.inflate(layoutInflater)
setContentView(binding.root)
// Inicializar SDK
stampsSDK = StampsSDK(this, this)
// Boton para iniciar captura
binding.btnCapture.setOnClickListener {
startDocumentCapture()
}
}
private fun startDocumentCapture() {
// Mostrar loading
binding.progressBar.visibility = View.VISIBLE
// Iniciar captura inteligente
stampsSDK.startStamps(1)
}
override fun onSuccessStamps(
typeProcess: Int,
frontOriginalUri: Uri?,
frontCropUri: Uri?,
backOriginalUri: Uri?,
backCropUri: Uri?,
frontFaceCropUri: Uri?
) {
binding.progressBar.visibility = View.GONE
// Determinar tipo de documento
val hasBack = backCropUri != null
val documentType = if (hasBack) "INE/IFE" else "Pasaporte/Licencia"
Toast.makeText(this, "Documento capturado: $documentType", Toast.LENGTH_SHORT).show()
// Procesar imagenes
processDocument(frontCropUri, backCropUri, frontFaceCropUri)
}
override fun onErrorStamps(error: String) {
binding.progressBar.visibility = View.GONE
Toast.makeText(this, "Error: $error", Toast.LENGTH_LONG).show()
Log.e("Stamps", error)
}
private fun processDocument(
frontUri: Uri?,
backUri: Uri?,
faceUri: Uri?
) {
// Convertir a Base64
val frontBase64 = frontUri?.let { Utils.uriToBase64(contentResolver, it) }
val backBase64 = backUri?.let { Utils.uriToBase64(contentResolver, it) }
val faceBase64 = faceUri?.let { Utils.uriToBase64(contentResolver, it) }
// Enviar a tu API
sendToServer(frontBase64, backBase64, faceBase64)
}
private fun sendToServer(front: String?, back: String?, face: String?) {
// Implementa tu logica de API aqui
lifecycleScope.launch {
try {
apiService.uploadDocument(front, back, face)
showSuccess()
} catch (e: Exception) {
showError(e.message)
}
}
}
}Preguntas Frecuentes (FAQ)
El SDK funciona offline?
Si, el SDK funciona completamente offline. No requiere internet para capturar ni procesar documentos. Solo necesita validar la licencia una vez al inicio (que se cachea).
Que formatos de imagen produce?
El SDK genera imagenes en formato JPEG optimizadas para procesamiento. Los archivos originales son de 1-5 MB, los recortados de 200-800 KB, y los rostros de 10-50 KB.
Puedo usar mi propio OCR?
Si, el SDK solo captura las imagenes. Tu decides que hacer con ellas: OCR, validacion, almacenamiento, etc.
Funciona con todos los dispositivos?
El SDK funciona en dispositivos Android 6.0+ (API 23) con camara funcional. Esta optimizado para todos los rangos (gama baja, media, alta).
Los datos se envian a servidores de JAAK?
No, el SDK trabaja completamente local. Las imagenes se guardan en el almacenamiento de tu app. Tu decides que hacer con ellas.
Cuanto espacio requiere?
El SDK en si ocupa aproximadamente 5 MB. Las imagenes capturadas varian segun configuracion, tipicamente 2-10 MB por documento completo.
Soporta documentos internacionales?
Si, el SDK detecta y captura cualquier documento tipo tarjeta. Esta optimizado para documentos mexicanos pero funciona con cualquier pais.
Contacto y Soporte
Soporte Tecnico
- Email: [email protected]
- Horario: Lunes a Viernes, 9:00 - 18:00 (UTC-6)
- Tiempo de respuesta: 24-48 horas
Solicitar Licencia
Para obtener una licencia del SDK:
- Enviar email a [email protected]
- Incluir: Nombre de empresa, package name de app, proposito de uso
- Licencias de desarrollo son gratuitas
- Licencias de produccion tienen costo segun volumen
Reportar Problemas
Si encuentras algun problema:
- Activa setShowDebugMode(true)
- Reproduce el error
- Copia los logs completos
- Envia email a soporte con:
- Descripcion del problema
- Logs de error
- Version del SDK
- Modelo y version de Android del dispositivo
- Capturas de pantalla si es posible
Ultima actualizacion: Noviembre 13, 2025
Version del documento: 1.0
Version del SDK: 1.2.0
Autor: JAAK AI - Equipo de Documentacion
Updated 4 days ago
