Qué le pasa a tu app cuando el usuario cambia de pantalla, cómo llamarlo de vuelta, y el tramo final que casi nadie enseña: publicarla de verdad.
Etiquetas
Lo que pasa cuando el usuario se va
Tu app casi nunca está en primer plano. El usuario entra treinta segundos, se va a responder un mensaje, vuelve diez minutos después, y en algún momento el sistema decide que necesita memoria y mata tu proceso sin avisar.
Ese es el ciclo de vida de una app móvil, y no tiene equivalente en web. Una pestaña abierta simplemente sigue ahí. Aquí no: aquí tu app vive a merced del sistema operativo.
AppState te dice en cuál de los tres estados estás —active, background, inactive— y es lo que te permite reaccionar. Pero lo que más sorprende es esto:
🚨 En segundo plano, tus timers y suscripciones siguen corriendo un rato. Gastando batería, consumiendo datos, en una app que el usuario ya no está viendo. Hasta que el sistema decide matarla, sin previo aviso.
De ahí las dos obligaciones: pausar lo caro al pasar a segundo plano (GPS, polling, reproducción) y guardar lo que no puedas perder antes, no "después" — porque puede no haber después. Es la misma pregunta de siempre, ahora a escala de aplicación: ¿y esto quién lo apaga?
Notificaciones push: qué son realmente
Las push son lo que más entusiasma al construir una app, así que vale la pena empezar por lo que no son: no son gratis y no son confiables.
El segundo snippet muestra el ciclo completo, y ahí está la sorpresa para muchos: necesitas un servidor. El dispositivo te da un token; alguien tiene que guardarlo y decidir cuándo enviar. Sin backend, no hay push — solo notificaciones locales, que son otra cosa (útiles, pero programadas desde el propio teléfono).
Tres cosas que conviene que sepas antes de prometerle push a un cliente:
- La entrega es "mejor esfuerzo", no garantizada ni inmediata. El sistema puede retrasarla o agruparla para ahorrar batería.
- El contenido se ve en la pantalla bloqueada. Nunca mandes datos sensibles en el cuerpo: "Tu resultado de laboratorio: positivo" es una filtración a la vista de cualquiera.
- Una notificación irrelevante cuesta carísimo. El usuario no desactiva esa: desactiva todas las de tu app, y no vuelve. El presupuesto de atención se gasta una sola vez.
Permisos: pedir bien es una habilidad
Ya aprendiste en la Auditoría IA #3 a manejar el permiso denegado. Aquí cerramos con cómo pedirlo para que te lo den:
- En contexto, cuando el usuario intenta usar la funcionalidad — no al abrir la app.
- Explicando el beneficio para él antes de que aparezca el diálogo del sistema. El diálogo es una sola bala.
- Con un texto humano. "Esta app necesita la cámara" no dice nada; "Para que puedas adjuntar la foto de tu recibo" sí.
Y recuerda el límite duro de Android: tras dos rechazos, canAskAgain se vuelve false y el diálogo ya no aparece nunca más. Si quemaste esa oportunidad al abrir la app, la perdiste para siempre.
Publicar: el tramo que nadie enseña
Aquí llega la parte que se aprende a golpes en el primer trabajo. Tu app puede estar técnicamente impecable y ser rechazada por la tienda en 24 horas — y casi nunca es por el código.
El cuarto snippet es el checklist completo, ordenado por frecuencia de rechazo. Los dos primeros bloques concentran la mayoría de los casos:
- Permisos declarados que no usas. Es la causa número uno en apps de estudiantes, y se arregla en dos minutos borrando líneas de
app.json. - Funcionalidad incompleta. Una pantalla que dice "Próximamente" es rechazo automático. Si algo no está listo, se quita del menú.
A eso se suman dos que cuestan la entrega entera por olvido: la política de privacidad (obligatoria si pides cualquier permiso) y la cuenta de prueba para el revisor (si tu app tiene login y el revisor no puede entrar, rechaza sin más).
El reto de hoy es justamente eso: un rechazo real que tienes que diagnosticar. Vale la pena que lo hagas antes de tu entrega final.
Cierre del semestre
Empezaste el curso encontrando div y onClick contrabandeados en un componente de React Native. Hoy sabes construir listas que no congelan el teléfono, formularios que sobreviven al teclado, features que respetan un permiso denegado, apps que funcionan en el metro y builds que una tienda podría aceptar.
Y lo más importante: en cada auditoría le pediste a una IA que escribiera código y decidiste tú qué entraba a tu proyecto. Esa es la habilidad que no caduca. Las APIs de esta clase van a cambiar; que sepas preguntar "¿y esto quién lo apaga?", "¿qué ve el usuario que dice que no?" y "¿esto funciona sin señal?" no va a cambiar nunca.
Ejemplos de Código
4 ejemplos
AppState — los tres estados de tu app
Y lo que sigue corriendo aunque el usuario no la vea.
1import { AppState } from "react-native";
2
3useEffect(() => {
4 const sub = AppState.addEventListener("change", (estado) => {
5 // "active" → en pantalla, el usuario la está usando
6 // "background" → el usuario se fue a otra app
7 // "inactive" → transición (iOS): llamada entrante, multitarea
8
9 if (estado === "background") pausarTrabajoPesado();
10 if (estado === "active") refrescarDatos();
11 });
12
13 return () => sub.remove(); // ← el cleanup de siempre
14}, []);
15
16🚨 Lo que sorprende: en segundo plano tus timers y suscripciones
17SIGUEN VIVOS un rato (gastando batería) hasta que el sistema decide
18matar el proceso. No hay aviso previo. Por eso:
19• Pausa lo caro al entrar a background (GPS, polling, video).
20• Guarda lo que no puedas perder ANTES, no "después".El ciclo completo de una notificación push
Por qué no es "gratis" y qué piezas necesita.
11. PERMISO la app pide permiso de notificaciones
2 (el usuario puede decir que no — y muchos lo hacen)
3
42. TOKEN el sistema le da a TU app un token de ESE dispositivo
5 (cambia si se reinstala la app; hay que refrescarlo)
6
73. TU SERVIDOR guardas ese token asociado al usuario
8 ← esta pieza es TUYA: sin backend no hay push
9
104. ENVÍO tu servidor le pide a Expo/FCM/APNs que entregue
11 el mensaje a ese token
12
135. ENTREGA el sistema operativo decide si la muestra
14 (puede retrasarla o agruparla para ahorrar batería)
15
166. TOQUE el usuario la toca → tu app debe abrir la pantalla
17 correcta, incluso si estaba cerrada
18
19Lo que casi nadie considera:
20• La entrega NO está garantizada ni es inmediata: es "mejor esfuerzo".
21• Nunca mandes información sensible en el cuerpo: se ve en la
22 pantalla bloqueada, a la vista de cualquiera.
23• Una notificación irrelevante cuesta carísimo: el usuario desactiva
24 TODAS las de tu app, y no vuelve a activarlas.Permisos — cómo se piden bien
En contexto, con justificación, y manejando el "no".
1// ❌ MAL: todos al abrir la app
2useEffect(() => {
3 pedirCamara(); pedirUbicacion(); pedirContactos();
4}, []);
5
6// ✅ BIEN: en el momento, explicando antes
7async function tomarFoto() {
8 const { status, canAskAgain } = await Camera.getCameraPermissionsAsync();
9
10 if (status !== "granted") {
11 if (!canAskAgain) {
12 // Android: ya dijo que no dos veces; el diálogo no volverá
13 return mostrarAviso("Actívalo en Ajustes", () => Linking.openSettings());
14 }
15 // Explica el beneficio ANTES del diálogo del sistema
16 const acepta = await mostrarExplicacion(
17 "Para adjuntar la foto de tu recibo necesitamos la cámara"
18 );
19 if (!acepta) return;
20
21 const nuevo = await Camera.requestCameraPermissionsAsync();
22 if (nuevo.status !== "granted") return mostrarAviso("Sin cámara no podemos continuar");
23 }
24
25 abrirCamara();
26}Checklist de publicación
Lo que revisan las tiendas, en orden de frecuencia de rechazo.
1IDENTIDAD
2 ☐ Icono propio (no el de Expo) en todas las resoluciones
3 ☐ Splash screen
4 ☐ Nombre definitivo y descripción real (sin "test" ni "demo")
5
6PERMISOS ← causa #1 de rechazo
7 ☐ Solo los que usas de verdad; borra el resto de app.json
8 ☐ Cada uno con texto que explique el BENEFICIO al usuario
9 ☐ Se piden en contexto, no al abrir
10
11COMPLETITUD ← causa #2
12 ☐ Cero pantallas "Próximamente" o "En construcción"
13 ☐ Cero funcionalidad simulada o de relleno
14 ☐ Cuenta de prueba para el revisor si hay login
15
16LEGAL
17 ☐ Política de privacidad con URL pública
18 ☐ Declaración de qué datos recolectas
19
20TÉCNICO
21 ☐ Versión y número de build asignados
22 ☐ Probada en dispositivo REAL, no solo en Expo Go
23 ☐ Sin logs de depuración ni llaves en el bundle
24 ☐ Tamaño razonable (revisa qué imágenes estás empaquetando)Recursos
4 recursos disponibles
¡Hora de Practicar!
Práctica Guiada — Deja tu app lista para entregar
El checklist real de publicación aplicado a tu proyecto.
Sobre tu proyecto integrador, antes de la defensa final:
- Ciclo de vida — encuentra en tu código todo lo que se registra (timers, suscripciones,
watchPosition) y verifica que se detenga al pasar a segundo plano o al desmontar. - Identidad — icono propio (no el de Expo) y pantalla de carga. Nombre definitivo de la app.
- Permisos — revisa tu
app.json: cada permiso declarado debe tener una razón visible en la app y un texto de justificación entendible para el usuario. Borra los que no uses. - Versión — asigna una versión (
1.0.0) y el número de build. - Build de producción — genera el instalable con EAS y pruébalo en un dispositivo real, no solo en Expo Go.
- Autocrítica de tienda — recorre la lista de causas de rechazo de la clase y anota honestamente cuáles te aplicarían hoy.
Entrega: el build compartible + tu autocrítica de tienda en el repo.
Desafío de Código
Ejercicios — Traza el ciclo de vida
Predecir qué sobrevive al segundo plano y qué no.
Para cada situación, di qué pasa con el código y qué debería pasar:
- Tienes un
setIntervalque refresca datos cada 10 s y el usuario cambia a WhatsApp por 20 minutos. - Tienes una suscripción de GPS con
watchPositionAsyncactiva y el usuario bloquea la pantalla. - El usuario deja tu app en segundo plano dos horas y el sistema mata el proceso. Vuelve a abrirla: ¿qué recuerda?
- Un video se está reproduciendo y entra una llamada.
- El usuario llenó medio formulario, se va a otra app y el sistema mata la tuya.
Después responde: ¿en cuáles de los cinco casos la solución es persistencia (clase 11) y en cuáles es ciclo de vida?
Reto de Lectura
Reto de Decisión — El rechazo de la tienda
Tu app fue rechazada. El correo de Apple es genérico y hay cinco causas reales. Diagnostícalas y ordena qué arreglar primero.
Terminaste tu app, la subiste a revisión y te la rechazaron. Este es el correo que llegó:
Guideline 5.1.1 — Data Collection and Storage
Guideline 2.1 — App Completeness
We were unable to approve your submission. Please review the
guidelines and resubmit.
Y esta es la ficha de tu envío:
Nombre: MiApp
Icono: el icono por defecto de Expo
Versión: 1.0.0
app.json — permisos declarados:
CAMERA "Esta app necesita la cámara"
ACCESS_FINE_LOCATION "Permiso de ubicación"
READ_CONTACTS (sin texto de justificación)
RECORD_AUDIO (sin texto de justificación)
Funcionalidad:
• La pantalla "Reportes" muestra "Próximamente"
• El login acepta cualquier correo sin validar (modo demo)
• La app pide TODOS los permisos al abrirse por primera vez
Política de privacidad: (campo vacío)
Cuenta de prueba para el revisor: no proporcionada
Preguntas:
- Identifica las 5 causas de rechazo y relaciónalas con las dos guidelines citadas.
- La app usa contactos y micrófono porque "quizá los necesitemos después". ¿Cuál es el problema y cuál es la regla general sobre permisos?
- ¿Por qué pedir todos los permisos al abrir es mala idea, incluso técnicamente?
- Ordena las cinco correcciones por esfuerzo y por impacto en la aprobación.
Documentación Oficial
Documentación de apoyo
Lo que vas a consultar el día que publiques.