Ingresa tus datos completos para iniciar la evaluación técnica de la Semana 12.
⏱️ Parte 1: cuestionario de 40 preguntas (mínimo 1 hora). Necesitas mínimo 25 respuestas correctas para obtener el punto.
🎡 Parte 2: ruleta de 5 retos prácticos (1 hora) en Android Studio.
Al dar clic en Iniciar Práctica Evaluada, el protocolo Anti-Fraude se activará de forma obligatoria.
Instrucciones: Lee atentamente el siguiente compendio técnico de la Semana 12 antes de responder el cuestionario interactivo de 40 preguntas (6 secciones, incluye 2 secciones de arrastre). Tiempo estimado mínimo: 1 hora. Para lograr el punto necesitas mínimo 25 respuestas buenas de 40. El contenido cubre la taxonomía completa de persistencia en Android, SharedPreferences, Ficheros Internos, Caché y Bases de Datos (SQLite y Room). Una vez completado el quiz, desbloquearás la Ruleta de Retos (Parte 2 — 1 hora) con 5 misiones de código en Android Studio.
Cátedra: Desarrollo de Aplicaciones Móviles I — UNICAES
En el ecosistema Android, cada aplicación se ejecuta dentro de su propio proceso de máquina virtual (ART - Android Runtime). La memoria RAM de este proceso actúa conceptualmente como una pizarra de aula de clases: es extraordinariamente rápida, eficiente para operaciones matemáticas y refresco de interfaz (60/120 Hz), pero es intrínsecamente volátil. Si el usuario rota la pantalla, entra una llamada telefónica, el sistema operativo mata el proceso en segundo plano por presión de memoria (Low Memory Killer - LMK) o el teléfono se apaga, todo dato almacenado exclusivamente en variables de memoria (Singletons, Companion Objects o ViewModels) es borrado de manera fulminante.
Por otro lado, la persistencia no volátil equivale a un cuaderno encuadernado en tinta: se escribe en la memoria de almacenamiento secundario (Flash NAND UFS / eMMC). Los datos permanecen intactos entre reinicios del dispositivo, cierres forzados de la aplicación y rotaciones de pantalla. Para todo desarrollador móvil, la regla cardinal es: La RAM es para el estado efímero del flujo presente; el almacenamiento no volátil es la única fuente fidedigna de verdad de la aplicación.
El framework de Android categoriza las opciones de almacenamiento en cinco niveles taxonómicos según su estructura, tamaño y ciclo de vida:
/data/data/<package_name>/files/. Completamente privados para la aplicación.SharedPreferences almacena datos en un archivo físico XML ubicado en /data/data/<package_name>/shared_prefs/. Para mutar sus valores, se debe invocar a la interfaz SharedPreferences.Editor:
Antipatrones de SharedPreferences: Jamás deben guardarse listas masivas de objetos JSON, imágenes en base64 ni contraseñas bancarias en texto plano. En la arquitectura moderna de Jetpack, Google introdujo Preferences DataStore, reemplazando SharedPreferences con una API basada en Corrutinas de Kotlin y Kotlin Flow, que garantiza seguridad de tipos y transacciones 100% asíncronas.
Android se apoya en el modelo de seguridad multiusuario del kernel de Linux. Al instalarse cada app, el sistema le asigna un identificador de usuario exclusivo (UID Linux). Todo archivo creado mediante context.openFileOutput("archivo.txt", Context.MODE_PRIVATE) o dentro de context.filesDir queda encapsulado en un Sandbox Privado. Ninguna otra aplicación puede leer, modificar ni listar esos archivos sin permisos explícitos de root.
En Kotlin profesional, la lectura y escritura de streams debe utilizar la función de extensión idiomática .use { ... }. Esta garantiza que el flujo de datos (FileOutputStream / FileInputStream) invoque automáticamente el método close() al terminar la operación, previniendo fugas graves de descriptores de archivos del sistema operativo incluso si se lanza una excepción.
Diferencia clave con cacheDir: Los archivos guardados en filesDir persisten indefinidamente hasta que el usuario desinstale la app o limpie los datos desde Configuración. En cambio, cacheDir está sujeto a limpieza automática preventiva por parte del sistema si el almacenamiento del dispositivo desciende por debajo de umbrales críticos de seguridad.
Scoped Storage (Almacenamiento Aislado): Desde Android 10 (API 29) y Android 11 (API 30), las apps ya no tienen acceso irrestricto a todo el almacenamiento compartido con WRITE_EXTERNAL_STORAGE. Para fotos y audio globales se debe emplear el MediaStore API, y para archivos arbitrarios externos, el Storage Access Framework (SAF).
Android incluye desde su versión 1.0 el motor de base de datos relacional nativo y embebido en C: SQLite. Es un motor transaccional completo (ACID), autocontenido y sin servidor (serverless), cuyos datos residen en un único archivo .db en el almacenamiento interno.
Históricamente, el acceso a SQLite se realizaba heredando de la clase abstracta SQLiteOpenHelper, sobreescribiendo sus dos métodos fundamentales:
CREATE TABLE.ALTER TABLE.Para manipular filas se utilizan objetos ContentValues (pares de columna-valor) y para leer resultados se utiliza un Cursor, el cual requiere iteración manual mediante cursor.moveToNext() y obtención por índice de columna (ej. cursor.getString(...)), sin olvidar invocar cursor.close().
La Revolución de Android Jetpack Room: La API clásica de SQLite carece de verificación de sintaxis SQL en tiempo de compilación y requiere una cantidad masiva de código repetitivo (Boilerplate). Por ello, Google desarrolló Room, la capa de abstracción oficial basada en tres componentes esenciales:
RoomDatabase y sirve como punto principal de acceso a las conexiones subyacentes.Regla de Hilos: Por defecto, Room prohíbe terminantemente ejecutar consultas en el Main Thread porque provocaría bloqueos de UI (lanzará una excepción IllegalStateException a menos que se usen corrutinas con funciones suspend o hilos de trabajo).
Uno de los puntos más importantes y que más se evalúa es entender la diferencia entre apply() y commit() en el SharedPreferences.Editor. Ambos métodos confirman los cambios, pero lo hacen de manera radicalmente diferente:
boolean indicando si la escritura fue exitosa. Si se ejecuta en el Main Thread con el disco ocupado, causa lag severo o ANR (Application Not Responding). Solo se recomienda cuando necesitas confirmar el guardado antes de continuar con un proceso crítico, y siempre fuera del UI Thread.Regla de oro: Si llamas a commit() en el hilo principal y la memoria flash está ocupada, la pantalla se congela. Si tarda más de 5 segundos, Android mata la aplicación con un ANR. Por eso Google introdujo apply() desde Android 2.3 (API 9).
Todo lo que vive únicamente en variables de memoria muere cuando Android necesita recursos. Estos son los 5 escenarios donde la RAM se pierde inevitablemente:
Test de 3 segundos: Si cierras la app y ese dato puede perderse sin que el usuario reclame → la RAM es correcto. Si el usuario espera que siga ahí → debes persistir.
SharedPreferences es ideal para persistir datos atómicos simples que configuran el comportamiento de la app:
true → abrir tutorial y cambiar a false. Si es false → ir directo al MainActivity.onCreate() lees el valor antes de setContentView() y aplicas el tema correcto al instante.editor.putInt("high_score", puntajeActual).apply().Antipatrones: NO guardar listas masivas de objetos JSON, imágenes en base64, contraseñas en texto plano, ni datos que requieran consultas complejas. Para eso existen archivos, Room o DataStore.
Android se apoya en el modelo de seguridad multiusuario del kernel de Linux. Al instalarse cada app, el sistema le asigna un identificador de usuario exclusivo (UID Linux). Todo archivo creado mediante context.openFileOutput() o dentro de context.filesDir queda encapsulado en un Sandbox Privado que ninguna otra aplicación puede leer sin permisos de root.
Desde Android 10 (API 29) y Android 11 (API 30), las apps ya no tienen acceso irrestricto a todo el almacenamiento compartido con WRITE_EXTERNAL_STORAGE. Para fotos y audio globales se debe emplear el MediaStore API, y para archivos arbitrarios externos, el Storage Access Framework (SAF).
cacheDir vs filesDir: Los archivos en filesDir persisten indefinidamente hasta que el usuario desinstale la app o limpie los datos. En cambio, cacheDir está sujeto a limpieza automática preventiva por parte del sistema si el almacenamiento del dispositivo desciende por debajo de umbrales críticos. La regla de oro: jamás guardar datos esenciales en caché; si se borran, la app debe ser capaz de re-descargarlos.
Room es la capa de abstracción oficial de Google sobre SQLite. Sus tres componentes esenciales son:
@Entity data class User(@PrimaryKey val id: Int, val name: String)Regla de hilos: Room prohíbe terminantemente ejecutar consultas en el Main Thread porque provocaría bloqueos de UI (lanzará una excepción IllegalStateException). Se deben usar corrutinas con funciones suspend o hilos de trabajo.
Ventaja sobre SQLite clásico: La API clásica de SQLiteOpenHelper carece de verificación de sintaxis SQL en tiempo de compilación y requiere una cantidad masiva de código repetitivo (boilerplate). Room elimina ambos problemas.
PUNTOS OBTENIDOS (mínimo 25/40 para el punto)
Captura esta pantalla con tu nombre y calificación para tu reporte de entrega. Si lograste ≥25, desbloqueas la Ruleta de Retos (Parte 2) a continuación. Si no, repasa y reintenta con el docente.
Revisa los temas señalados a continuación en la lectura técnica para consolidar los conceptos clave:
Cada estudiante gira la ruleta y se le asigna 1 de 5 retos fáciles (sin SQLite: solo SharedPreferences, archivos y DataStore). Desarrolla solo tu reto asignado en Android Studio (Kotlin) y documenta con capturas + código en tu PDF final. Tiempo estimado: 1 hora.
⚠️ SOLO 1 giro por estudiante (queda guardado). Toma captura de tu resultado como evidencia.
📌 Disponible hasta las 8:15 PM (hora de El Salvador). Después de esa hora la práctica se bloquea.
Pantalla con Switch (Modo Nocturno) + EditText (carné). Al presionar Guardar, persiste con apply() y al reabrir todo sigue igual.
implementation("com.google.android.material:material:1.12.0")Login con usuario + CheckBox. Si está marcado, guarda activa=true + user y al reabrir entra directo. Botón Salir borra la sesión con clear().
implementation("com.google.android.material:material:1.12.0")Bloc de notas que guarda en el archivo privado nota.txt (filesDir) y lo lee al abrir. Cierra el stream siempre con .use { }.
implementation("com.google.code.gson:gson:2.10.1") // opcional: nota como JSONPerfil que guarda el nombre en SharedPreferences y la foto como foto_perfil.jpg en filesDir. Al reabrir, muestra nombre + foto con Coil.
implementation("io.coil-kt:coil:2.5.0")implementation("com.google.android.material:material:1.12.0")Lista de 3 favoritos con corazón que se guarda en DataStore con corrutinas y se observa con Flow. Al reabrir, los corazones siguen igual.
implementation("androidx.datastore:datastore-preferences:1.1.1")implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")Exporta tu informe con la captura de la evaluación (≥25/40), la captura de tu ruleta y el código de tu reto asignado en PDF y súbelo a la plataforma institucional. Recuerda: en clase entregas SOLO tu reto; fuera de tiempo, los 5 casos.