Automatiza tareas en Android con los Workflows de Pocket Code: disparadores por eventos, cron programado en el móvil, reintentos y editor visual, sin servidor.
Todo desarrollador acumula las mismas pequeñas tareas repetitivas: lanzar los tests después de un push, hacer una copia de seguridad de la base de datos cuando sale un deploy, formatear al guardar, avisarte cuando falla un build. En un portátil lo unes todo con runners de CI, tareas cron y un par de scripts de shell en algún servidor. En un móvil, la respuesta de siempre es «no se puede». Pocket Code cambia eso con los Workflows: un motor de automatización basado en eventos que te permite automatizar tareas en Android por completo en el dispositivo, sin ningún servidor que alquilar ni nada que mantener vivo en la nube.
Un workflow es sencillo de describir: un disparador (un evento dentro del IDE o una programación) más una secuencia de pasos que se ejecutan sobre un contexto compartido. Eso basta para construir flujos de desarrollo reales —del tipo para el que normalmente montarías un pipeline de CI— justo al lado de tu editor, tu terminal y tu gestor de base de datos.
Nunca tienes que empezar desde un lienzo en blanco. El módulo te ofrece tres puntos de partida:
| Modo | Cómo lo creas | Ejemplo |
|---|---|---|
| Plantilla | Toca Activar en una de las 8 plantillas integradas | "CI/CD Pipeline", "Auto-Deploy on Push", "DB Backup on Deploy" |
| Generar con IA | Escribe un prompt y obtén un esqueleto editable | "cuando haya push a main, despliega y notifica" se convierte en un workflow de 2 pasos |
| Editor | Toca el botón "+" (FAB) para el formulario completo | Constrúyelo desde cero con bindings y políticas de reintento |
Activar una plantilla la clona en una copia editable con un ID nuevo, así que puedes ajustarla sin tocar el original.
Los workflows escuchan los eventos que fluyen por el IDE. El motor se suscribe al bus de eventos interno de la app y asocia cada evento a un tipo de disparador. Hay diez tipos de disparador:
| Disparador | Se dispara con | Filtro típico |
|---|---|---|
GIT_PUSH | Un push completado | rama ("main", "develop") |
GIT_COMMIT | Un nuevo commit | rama |
FILE_SAVED | Al guardar un archivo en el editor | extensión (".kt", ".ts") |
APP_FOREGROUNDED | La app pasando a primer plano | — |
TERMINAL_COMMAND_FINISHED | Un comando de terminal que termina | patrón de comando |
DATABASE_QUERY_EXECUTED | Un resultado de consulta que llega | nombre de tabla |
DEPLOYMENT_COMPLETED | Un deploy correcto | proveedor ("vercel", "railway") |
DEPLOYMENT_FAILED | Un deploy fallido | proveedor |
ERROR_DETECTED | Otro workflow que falla | nombre de workflow / patrón de error |
MANUAL | Nada; se ejecuta por programación o a mano | — |
Solo entran en evaluación los workflows habilitados cuyo tipo de disparador
coincide, y un filtro opcional lo acota aún más con una coincidencia de
subcadena que no distingue mayúsculas de minúsculas, de modo que un workflow
GIT_PUSH filtrado a main ignora cualquier otra rama.
Aquí es donde la «automatización sin servidor» se vuelve concreta. Un workflow con
un disparador MANUAL y una programación asociada se convierte en una tarea
programada. Por debajo, el programador envuelve el WorkManager de Android y
ofrece dos modos.
Las programaciones por intervalo usan una petición de trabajo periódica. El
mínimo de WorkManager es de 15 minutos, así que los valores más cortos se
elevan hasta ese límite. Los presets:
| Preset | Intervalo |
|---|---|
EVERY_15_MIN | 15 min |
HOURLY | 60 min |
EVERY_6_HOURS | 360 min |
Las programaciones cron son la parte interesante. Pocket Code incorpora su
propio parser de cron de 5 campos (minuto, hora, día del mes, mes, día de la
semana) —sin librería externa— compatible con comodines *, valores únicos,
listas N,M, rangos N-M y pasos */N. Hay dos presets de cron integrados:
DAILY_9AM — 0 9 * * *WEEKLY_MON_9AM — 0 9 * * 1Como la API periódica de WorkManager no puede expresar un cron real, cada
ejecución de cron se programa como una tarea puntual que rearma el siguiente
disparo cuando termina, manteniendo el cron vivo de forma indefinida. El editor
de programación muestra una vista previa en vivo de «Próximo disparo» calculada a
partir de tu expresión, y se pone en rojo con «Expresión cron no válida» en el
momento en que falla el análisis: feedback inmediato antes de guardar. El parser
mantiene las cosas simples a propósito en esta versión: los nombres de mes y
día, ?, L, #, los segundos y el año no son compatibles.
Las programaciones se persisten y se vuelven a encolar al arrancar la app, de modo que la muerte de un proceso no vacía tu automatización sin que te enteres.
El editor es un formulario completo: nombre, descripción, un interruptor de
activado, un desplegable de disparador con un filtro opcional y una lista vertical
de tarjetas de paso que puedes reordenar, editar o eliminar. Añadir un paso abre
un selector dividido en Control de flujo (Wait, If / Else) y Acciones:
los ocho tipos de acción, cada uno con una etiqueta legible y un formulario de
configuración dinámico:
| ActionType | Campos del formulario |
|---|---|
RUN_COMMAND | command |
NOTIFICATION | title, message |
AI_ANALYZE | prompt, language (opcional) |
AI_GENERATE | prompt, language (opcional) |
GIT_OPERATION | operation (commit/push/pull), branch, message |
DEPLOY | branch (opcional) |
DATABASE_BACKUP | command (opcional) |
OPEN_FILE | file (ruta), line (opcional) |
Cada paso de acción tiene además secciones plegables de Fiabilidad y Condicional (más sobre eso más abajo). Nada llega a la base de datos hasta que pulsas Guardar en la barra superior: aplicar y cancelar trabajan sobre el estado local del editor, así que puedes experimentar con libertad. Guardar solo se habilita una vez que el workflow tiene un nombre y al menos un paso.
El editor expone Wait y un nivel de If / Else hoy por hoy. El propio motor
también ejecuta pasos Loop, Parallel y TryCatch, pero un editor visual para
esos es un siguiente paso conocido más que una superficie ya disponible, así que
trátalos como bloques de construcción a nivel de motor, no como algo que puedas
arrastrar desde el selector todavía.
Los pasos no se ejecutan de forma aislada: comparten un contexto, y cualquier
campo de valor puede referenciar un paso anterior con un {{binding}}. La
sintaxis:
| Expresión | Se resuelve a |
|---|---|
{{var.<name>}} | Una variable de contexto |
{{step.<id>.status}} | El estado de un paso |
{{step.<id>.output.<field>}} | Un campo de la salida de un paso |
{{step.<id>.error}} | El mensaje de error de un paso |
{{item.<alias>}} | El elemento actual dentro de un loop |
{{trigger.eventName}} | El evento que inició la ejecución |
Una expresión que no se resuelve devuelve una cadena vacía a propósito, de modo
que un binding a un paso que nunca se ejecutó (por ejemplo, en una rama
condicional que se saltó) no revienta toda la ejecución. Las condiciones se
construyen sobre la misma idea, con operadores Equals, NotEquals,
GreaterThan, LessThan, Contains, IsNull y los booleanos And / Or /
Not comparando valores resueltos.
Una automatización en la que no puedes confiar no es automatización. Cada paso de acción admite una política de reintentos y un timeout, expuestos en esa sección plegable de Fiabilidad:
| Ajuste | Valor por defecto |
|---|---|
| Máximo de intentos | 1 (sin reintento) |
| Estrategia de backoff | EXPONENTIAL |
| Retardo inicial | 500 ms |
| Retardo máximo | inicial × 30 |
| Timeout | ninguno |
El backoff viene en variantes fija, lineal y exponencial (duplicación
exponencial: 500, 1000, 2000, 4000…), cada una limitada por el retardo máximo. Los
timeouts son timeouts reales de coroutine: cuando salta uno, el paso se marca como
TIMED_OUT. También hay una condición _when ligera en las acciones
individuales: enlázala a un valor y el paso se salta cuando ese valor está vacío,
es false, 0 o null, de modo que puedes condicionar un solo paso sin
envolverlo en un condicional completo.
Cada ejecución se persiste con una instantánea completa de los resultados de sus
pasos, lo que significa que el historial sobrevive a los cierres inesperados. La
línea de tiempo de Ejecuciones lista las ejecuciones de la más reciente a la
más antigua con un icono de estado, marca de tiempo, número de pasos, duración y
una vista previa de error de una línea si algo falló. Al tocar una ejecución se
abre un desglose paso a paso: color de estado por paso (éxito, fallo, saltado,
con timeout, en ejecución), la duración del paso, su salida renderizada como pares
clave=valor y cualquier cadena de error.
La retención es automática: el repositorio conserva las últimas 100 ejecuciones por workflow y descarta todo lo más antiguo de 30 días, de modo que el historial sigue siendo útil sin crecer sin límite.
Ocho plantillas inmutables cubren los casos habituales, así que puedes tener una automatización funcionando con un solo toque:
| Plantilla | Disparador | Acciones |
|---|---|---|
tpl_ci_cd | GIT_PUSH | npm test → deploy → notificar |
tpl_auto_deploy | GIT_PUSH (main) | deploy → notificar |
tpl_db_backup | DEPLOYMENT_COMPLETED | copia de la base de datos → notificar |
tpl_error_ai | ERROR_DETECTED | notificar → IA "sugiere un arreglo" |
tpl_auto_format | FILE_SAVED | prettier --write . |
tpl_auto_commit | FILE_SAVED | git add -A && git commit |
tpl_branch_protect | GIT_PUSH (main) | npm test → notificar |
tpl_test_commit | GIT_COMMIT | npm test → notificar |
Si prefieres no ensamblar los pasos a mano, el Generador con IA convierte un
prompt en un workflow editable. Lee palabras clave para inferir un disparador
("push", "deploy failed", "error", "save"…) y una secuencia de acciones ("deploy",
"backup", "test", "format", "notify"…), y luego muestra una vista previa que
puedes Guardar y activar o descartar. Un prompt como "cuando haya push a main,
despliega y notifica" produce un workflow de dos pasos conectado a GIT_PUSH en
main. El generador también tiene una vía respaldada por LLM que usa tu proveedor
de IA configurado y recurre en silencio al parser heurístico si algo sale mal, así
que siempre obtienes una vista previa o un mensaje claro de «no se pudo inferir».
Las definiciones de workflow, el historial de ejecuciones y las programaciones
viven en una base de datos local en tu móvil. Las definiciones pueden
respaldarse en la nube para restaurarlas, pero nunca se lee nada de la nube para
ejecutar tu automatización: el motor se ejecuta localmente, punto. El historial
de ejecuciones y las programaciones no se sincronizan en absoluto: el historial es
local del dispositivo, y las programaciones son estado de WorkManager específico
de cada dispositivo. Tu automatización es tuya, y se ejecuta donde estás.
Pocket Code va camino de Google Play, llevando un motor de automatización completo —disparadores, programación cron en el móvil, reintentos y editor visual— a la misma app donde escribes y publicas el código. Apúntate al preregistro para estar entre los primeros en probarlo en tu propio dispositivo.
Descarga la app y empieza a programar desde tu móvil.