Taller de Desarrollo Móvil en Android

Ingeniería de Software y Sistemas Computacionales | La Salle Nezahualcóyotl

Práctica 4: SharedPreferences y Gestión de Sesión

Objetivo: Implementar persistencia de datos para que la aplicación "recuerde" al usuario después de cerrarse.

Paso 1: Interfaz de Usuario (Cerrar Sesión)

Añadiremos un botón en la parte superior de nuestra lista actual.

📍 Archivo: app > res > layout > activity_home.xml

Sustituye todo el código por este bloque:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btnCerrarSesion"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:text="Cerrar Sesión"
        android:backgroundTint="#e31b23" 
        android:textColor="#ffffff" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvUsuarios"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

</LinearLayout>

Paso 2: Guardar Datos en MainActivity

Actualizaremos la lógica del botón de ingreso para grabar el nombre en el dispositivo.

📍 Archivo: MainActivity.kt

Localiza tu boton.setOnClickListener e integra las líneas de persistencia:

boton.setOnClickListener {
    val nombreUsuario = cuadroTexto.text.toString()

    if (nombreUsuario.trim().isNotEmpty()) {
        
        // --- PERSISTENCIA ---
        val preferencias = getSharedPreferences("PREFS_SESION", MODE_PRIVATE)
        val editor = preferencias.edit()
        editor.putString("USER_NAME", nombreUsuario)
        editor.apply() 
        // --------------------

        val pasarPantalla = Intent(this, HomeActivity::class.java)
        pasarPantalla.putExtra("USER_NAME", nombreUsuario)
        startActivity(pasarPantalla)
    } else {
        Toast.makeText(this, "Por favor, ingresa un nombre", Toast.LENGTH_SHORT).show()
    }
}

Paso 3: Validación Automática al Abrir

Haremos que la app revise si ya hay una sesión activa antes de mostrar el Login.

📍 Archivo: MainActivity.kt (Dentro de onCreate)
// 1. Intentar leer el archivo de preferencias
val prefs = getSharedPreferences("PREFS_SESION", MODE_PRIVATE)
val usuarioGuardado = prefs.getString("USER_NAME", null)

// 2. Si existe un dato, saltar directo a HomeActivity
if (usuarioGuardado != null) {
    val intent = Intent(this, HomeActivity::class.java)
    intent.putExtra("USER_NAME", usuarioGuardado)
    startActivity(intent)
    finish() // Destruye MainActivity de la pila
}

Paso 4: Finalizar Sesión en HomeActivity

Programaremos el botón para limpiar el almacenamiento local.

📍 Archivo: HomeActivity.kt
// Al final del método onCreate
val botonLogout = findViewById<Button>(R.id.btnCerrarSesion)

botonLogout.setOnClickListener {
    val editor = getSharedPreferences("PREFS_SESION", MODE_PRIVATE).edit()
    editor.clear() 
    editor.apply()

    Toast.makeText(this, "Sesión finalizada", Toast.LENGTH_SHORT).show()
    finish()
}

📝 Módulo de Evaluación: Práctica 4

Responde las siguientes preguntas basándote en la implementación técnica realizada en el laboratorio.

1. Análisis de Persistencia:

Al usar getSharedPreferences("PREFS_SESION", MODE_PRIVATE), ¿qué sucede con los datos si el usuario fuerza el cierre de la aplicación desde el administrador de tareas? Justifica tu respuesta basándote en el método .apply().

2. Gestión de la Pila de Actividades (Backstack):

En el Paso 3, implementamos finish() después de iniciar la HomeActivity. ¿Qué problema de seguridad o de experiencia de usuario (UX) ocurriría si omitiéramos esta instrucción?

3. Seguridad y Encapsulamiento:

El parámetro MODE_PRIVATE es fundamental en la creación del archivo de preferencias. Desde la perspectiva de seguridad en Android, ¿qué impide este modo de operación respecto a otras aplicaciones instaladas en el mismo dispositivo?

4. Ciclo de Vida y Estados:

Si un alumno coloca la validación de la sesión (Paso 3) en el método onResume() en lugar del onCreate(), ¿qué diferencia de comportamiento notaría el usuario al navegar entre actividades?

💡 Nota para el reporte: Incluye capturas de pantalla de tu emulador mostrando el ingreso automático después de reiniciar la app y el regreso al login tras presionar "Cerrar Sesión".