██╗   ██╗███╗   ██╗██╗██╗   ██╗███████╗██████╗ ███████╗ █████╗ ██╗
██║   ██║████╗  ██║██║██║   ██║██╔════╝██╔══██╗██╔════╝██╔══██╗██║
██║   ██║██╔██╗ ██║██║╚██╗ ██╔╝█████╗  ██████╔╝███████╗███████║██║
██║   ██║██║╚██╗██║██║ ╚████╔╝ ██╔══╝  ██╔══██╗╚════██║██╔══██║██║
╚██████╔╝██║ ╚████║██║  ╚██╔╝  ███████╗██║  ██║███████║██║  ██║███████╗
 ╚═════╝ ╚═╝  ╚═══╝╚═╝   ╚═╝   ╚══════╝╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚══════╝
                    C O D E   S C A N N E R

Un lector de códigos que asume que un código puede mentir.
Interpreta el contenido, lo explica en campos legibles, evalúa 16 señales de riesgo locales
y espera una confirmación explícita antes de ejecutar cualquier acción externa.

Estado de la integración continua Flutter 3.44.7 Android, iOS, macOS y Web Versión 1.1.0 57 pruebas en verde Licencia MIT Telemetría cero

Interpretar primero. Actuar después.

🔍 Qué problema resuelve

Un QR es una instrucción opaca: nadie puede leer a simple vista si lleva a un banco o a una copia del banco. La mayoría de los lectores resuelve esa ambigüedad abriendo el enlace de inmediato. Este hace lo contrario.

Pregunta Cómo responde Universal Code Scanner
¿A dónde lleva realmente este QR? Muestra dominio, protocolo, ruta y consulta antes de abrir nada.
¿Este enlace intenta engañarme? 16 señales locales: Punycode, alfabetos mezclados, credenciales en la URL, IP literal, acortador, descarga ejecutable…
¿Qué dice un código que no es un enlace? Interpreta Wi-Fi, vCard, eventos, OTP, GS1, ISBN, EMVCo, SEPA, Swiss QR, criptomonedas y AAMVA.
¿Puedo contar existencias con el teléfono? Sesiones de inventario con conteo, notas y exportación a CSV, XLSX y JSON.
¿Y si el código está en un PDF o en fotos? Lotes de hasta 20 imágenes y 50 páginas, con progreso y cancelación.
¿Queda mi historial expuesto? Cifrado AES-256-GCM en disco; OTP y Wi-Fi con contraseña nunca se guardan solos.
¿Qué pasa si la base se corrompe? Modo temporal en memoria y Centro de recuperación por registro.
¿Necesito generar un código? Generador PNG y SVG de 10 simbologías.
¿Está escaneando ahora mismo? Barra de estado permanente: solo se mueve mientras el motor analiza cuadros.

📸 La aplicación en marcha

Capturas del APK release corriendo en el emulador oficial de Android (API 36). La pestaña Escanear corresponde a 1.1.0 y muestra la barra de estado en «Escaneando»; las demás se tomaron en 1.0.0 sobre pantallas que no han cambiado.

Pestaña Escanear: barra de estado en «Escaneando», marco con esquinas y línea de lectura, zoom, linterna, pausa, cambio de cámara y reinicio
Escanear — estado siempre visible
Pestaña Generar: tipo de contenido, formato, corrección de errores y QR renderizado
Generar — 10 simbologías
Pestaña Historial: buscador y filtros por nivel de riesgo
Historial — cifrado en disco
Pestaña Inventario: sesiones con nombre e importación JSON
Inventario — conteo y exportación
Pestaña Ajustes: apariencia, idioma, accesibilidad y opciones del escáner
Ajustes — apariencia y escáner

🎯 Cómo se comporta el escáner

La lectura es automática: no hay que pulsar nada para leer un código. Lo que sí está siempre a la vista es en qué estado se encuentra la cámara, porque una cámara que no arranca no puede parecerse a una cámara esperando un código.

Estado Qué se ve Qué se ofrece
Iniciando cámara Barra en movimiento
Escaneando Barra en movimiento y línea que recorre el marco Botón «Pausar»
Escaneo en pausa Barra detenida y vista atenuada «Reanudar escaneo», o tocar la vista
Cámara no disponible Barra en color de error y motivo concreto «Reintentar» y «Reiniciar cámara»
🔔

Tono propio, no el del sistema

Cada lectura conseguida suena con un tono empaquetado en la aplicación —no con el efecto de sonido del sistema, que Android silencia en cuanto se apagan los sonidos táctiles— y vibra. Sonido y vibración son ajustes independientes.

Movimiento reducido

Con movimiento reducido activado, la barra de estado y el marco se dibujan quietos: la información sigue estando, la animación no.

🧩

Cuando un código no entra

La landing no adivina por ti: la guía de diagnóstico por síntoma —encuadre, recorte de lectura, permiso denegado, silencio— está en SCANNER_UX.md, con la causa técnica de cada fallo corregido en 1.1.0.

🧾 Formatos

La cobertura real de cada simbología depende del backend activo —ML Kit, Apple Vision o el motor web—. Detalle y exclusiones en SUPPORTED_FORMATS.md.

Categoría Cobertura en 1.1.0
2D QR, Micro QR, Data Matrix, Aztec, PDF417, MaxiCode
Lineales Code 128, Code 39, Code 93, Codabar, EAN-13, EAN-8, UPC-A, UPC-E, ITF
GS1 DataBar, DataBar Expanded, DataBar Limited, Application Identifiers
Contenidos URL, texto, binario, Wi-Fi, vCard, MeCard, vEvent, correo, teléfono, SMS, geo, OTP, ISBN, producto
Pagos EMVCo, EPC/SEPA, Swiss QR Bill, Bitcoin, Lightning, Ethereum
Identidad AAMVA/PDF417 reconocible
Generación QR, Data Matrix, Aztec, PDF417, Code 128, Code 39, EAN-13, EAN-8, UPC-A, GS1-128

🔐 Del código a la acción

Ninguna rama de este flujo abre un enlace, marca un teléfono ni conecta una red sin que la persona lo confirme viendo antes los campos interpretados.

Flujo: captura, interpretación, análisis de riesgo, confirmación explícita y persistencia cifrada

🛡️ Seguridad y privacidad

Todo ocurre en el dispositivo. Sin cuentas, sin publicidad, sin analítica, sin servidores propios.

Garantía Implementación
Nada se abre solo Confirmación explícita para cada acción externa
Historial cifrado AES-256-GCM con nonce y MAC por registro
Llave protegida Keychain / Keystore vía flutter_secure_storage
Llave ausente ≠ llave nueva El descifrado falla, informa y bloquea escrituras con ese identificador
Rotación segura Reencriptado completo dentro de una transacción; llave huérfana eliminada si falla
Secretos efímeros OTP y Wi-Fi con contraseña fuera del historial; portapapeles con borrado programado
Diagnóstico sin datos Solo tipo de error y huella de pila: nunca cargas, URLs ni notas
Telemetría Cero. No hay red saliente propia

📱 Plataformas

Las carpetas nativas no se versionan: se generan de forma reproducible con tool/bootstrap.py, que además aplica permisos, minSdk, entitlements, descripciones de uso, la cadena de compilación de Gradle y los iconos. Así el repositorio contiene únicamente fuente propia.

Plataforma Estado en 1.1.0 Notas
Android (API 24+) APK compilado y ejecutado en emulador Motor ML Kit vía mobile_scanner
iOS (15.5+) Compila en CI (--no-codesign) Motor Apple Vision · sin ejecución verificada
macOS Compila en CI Cámara y galería · sin ejecución verificada
Web / PWA Compila y se ejecuta (release) Es la versión publicada en /app/ · sin lectura de PDF local
Windows · Linux Vía PWA Sin motor nativo en 1.1.0

En pantallas anchas —navegador de escritorio o tablet— la interfaz se centra con un ancho máximo de teléfono en lugar de estirarse de borde a borde.

⬇ Descargar

Los APK de cada versión están en Releases. Cada archivo publica su SHA-256 en checksums.txt para que puedas verificar la descarga.

Recomendado

app-arm64-v8a-release.apk

Prácticamente cualquier móvil actual.

32,8 MB · 1.1.0

Ir al release

app-armeabi-v7a-release.apk

Móviles antiguos de 32 bits.

26,8 MB · 1.1.0

app-x86_64-release.apk

Emuladores y equipos x86.

35,3 MB · 1.1.0

app-release.apk

Universal: funciona en todos, pesa el triple.

88,1 MB · 1.1.0

Estos APK están firmados con la clave de depuración de Android (CN=Android Debug), porque 1.1.0 no incluye firma de publicación. Sirven para instalar y probar. No sirven para subir a Google Play, y una versión futura firmada con una clave propia no podrá actualizarlos: habrá que desinstalar antes. Android pedirá permiso para instalar desde una fuente desconocida; es el flujo normal de cualquier APK que no venga de una tienda.

¿Prefieres no instalar nada? La misma aplicación corre en el navegador en /app/: pedirá el permiso de cámara del navegador y, como toda la versión web, no lee PDF locales.

✅ Calidad verificada

Ejecutado con Flutter 3.44.7 sobre esta misma versión del código.

Comprobación Resultado
flutter analyze --fatal-infos 0 hallazgos
flutter test 57 de 57 en verde
flutter build web --release Compila
flutter build apk --release Compila los cuatro APK publicados
Tono de lectura dentro del APK Presente en los cuatro artefactos, no solo en el repositorio
Instalación y arranque Emulador Android API 36: la cámara transmite y la barra marca «Escaneando»
SHA-256 del APK publicado El archivo descargado del release coincide con checksums.txt

Lo que no se ha verificado todavía está declarado sin adornos en VALIDATION.md y IMPLEMENTATION_STATUS.md: esta versión no ha sido probada en dispositivos físicos.

🚧 Límites declarados de 1.1.0

Esta versión prefiere decir lo que no hace antes que insinuar que lo hace.

📚 Documentación

Todo lo que sostiene lo anterior, en el repositorio.

Arquitectura Capas, flujo de lectura y puntos de extensión
Seguridad Modelo aplicado y señales de URL
Modelo de amenazas Actores, superficies y mitigaciones
Privacidad Qué se guarda, dónde y por cuánto tiempo
Formatos Simbologías, contenidos y exclusiones
UX del escáner Estados, causas de fallo y comparación con otros lectores
Accesibilidad Contraste, lectores de pantalla e idiomas
Changelog Qué cambió en cada versión