Blog para desarrollo de aplicaciones en Android, aprende paso a paso como crear aplicaciones.

Usamos cookies propias y de terceros que entre otras cosas recogen datos sobre sus hábitos de navegación para mostrarle publicidad personalizada y realizar análisis de uso de nuestro sitio.
Si continúa navegando consideramos que acepta su uso. OK Más información | Y más

SharedPreferences en Android

SharedPreferences en Android

Hola amigos 👋 Bienvenidos a un nuevo tutorial de Universo Android. Hoy aprenderemos a usar SharedPreferences, el sistema de almacenamiento local más simple y eficiente para guardar datos pequeños en formato clave-valor.

Al finalizar este tutorial tendrás una aplicación que incluirá:

  • Guardar y leer datos simples
  • Almacenar diferentes tipos de datos
  • Preferencias de usuario
  • Sistema de login persistente
  • Configuraciones de la app
  • Modo oscuro/claro
  • Limpiar datos almacenados

🟩 1. ¿Qué es SharedPreferences?

SharedPreferences es un sistema de almacenamiento que guarda datos en formato clave-valor en archivos XML. Es ideal para configuraciones, preferencias de usuario y datos pequeños que necesitan persistir.

🟩 2. Tipos de Datos Soportados

  • String
  • int
  • long
  • float
  • boolean
  • Set<String>

🟩 3. Crear el Proyecto

Creamos un nuevo proyecto en Android Studio con Empty Activity.

🟩 4. Clase Helper para SharedPreferences

📄 SharedPreferencesManager.java

import android.content.Context;
import android.content.SharedPreferences;

public class SharedPreferencesManager {

    private static final String PREF_NAME = "MyAppPreferences";
    private static final String KEY_IS_LOGGED_IN = "isLoggedIn";
    private static final String KEY_USER_NAME = "userName";
    private static final String KEY_USER_EMAIL = "userEmail";
    private static final String KEY_USER_ID = "userId";
    private static final String KEY_DARK_MODE = "darkMode";
    private static final String KEY_NOTIFICATIONS = "notifications";
    private static final String KEY_LANGUAGE = "language";
    private static final String KEY_FIRST_TIME = "firstTime";

    private SharedPreferences prefs;
    private SharedPreferences.Editor editor;

    public SharedPreferencesManager(Context context) {
        prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
        editor = prefs.edit();
    }

    // Guardar login
    public void saveLoginData(String userName, String email, int userId) {
        editor.putBoolean(KEY_IS_LOGGED_IN, true);
        editor.putString(KEY_USER_NAME, userName);
        editor.putString(KEY_USER_EMAIL, email);
        editor.putInt(KEY_USER_ID, userId);
        editor.apply();
    }

    // Verificar si está logueado
    public boolean isLoggedIn() {
        return prefs.getBoolean(KEY_IS_LOGGED_IN, false);
    }

    // Obtener nombre de usuario
    public String getUserName() {
        return prefs.getString(KEY_USER_NAME, "");
    }

    // Obtener email
    public String getUserEmail() {
        return prefs.getString(KEY_USER_EMAIL, "");
    }

    // Obtener ID de usuario
    public int getUserId() {
        return prefs.getInt(KEY_USER_ID, -1);
    }

    // Guardar modo oscuro
    public void setDarkMode(boolean enabled) {
        editor.putBoolean(KEY_DARK_MODE, enabled);
        editor.apply();
    }

    // Obtener estado modo oscuro
    public boolean isDarkMode() {
        return prefs.getBoolean(KEY_DARK_MODE, false);
    }

    // Guardar notificaciones
    public void setNotifications(boolean enabled) {
        editor.putBoolean(KEY_NOTIFICATIONS, enabled);
        editor.apply();
    }

    // Obtener estado notificaciones
    public boolean isNotificationsEnabled() {
        return prefs.getBoolean(KEY_NOTIFICATIONS, true);
    }

    // Guardar idioma
    public void setLanguage(String language) {
        editor.putString(KEY_LANGUAGE, language);
        editor.apply();
    }

    // Obtener idioma
    public String getLanguage() {
        return prefs.getString(KEY_LANGUAGE, "es");
    }

    // Primera vez
    public boolean isFirstTime() {
        return prefs.getBoolean(KEY_FIRST_TIME, true);
    }

    // Marcar como no primera vez
    public void setFirstTime(boolean firstTime) {
        editor.putBoolean(KEY_FIRST_TIME, firstTime);
        editor.apply();
    }

    // Cerrar sesión
    public void logout() {
        editor.putBoolean(KEY_IS_LOGGED_IN, false);
        editor.remove(KEY_USER_NAME);
        editor.remove(KEY_USER_EMAIL);
        editor.remove(KEY_USER_ID);
        editor.apply();
    }

    // Limpiar todas las preferencias
    public void clearAll() {
        editor.clear();
        editor.apply();
    }
}

🟩 5. Diseño XML Principal

📄 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="SharedPreferences Demo"
            android:textSize="24sp"
            android:textStyle="bold"
            android:textColor="#2196F3"
            android:layout_marginBottom="24dp" />

        <!-- Sección de Login -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Datos de Usuario"
            android:textSize="18sp"
            android:textStyle="bold"
            android:layout_marginBottom="16dp" />

        <EditText
            android:id="@+id/txtUserName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Nombre de usuario"
            android:padding="12dp"
            android:background="@drawable/edittext_background" />

        <EditText
            android:id="@+id/txtEmail"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Email"
            android:inputType="textEmailAddress"
            android:padding="12dp"
            android:background="@drawable/edittext_background"
            android:layout_marginTop="12dp" />

        <Button
            android:id="@+id/btnSave"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Guardar Datos"
            android:layout_marginTop="16dp" />

        <Button
            android:id="@+id/btnLoad"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Cargar Datos"
            android:layout_marginTop="8dp" />

        <!-- Separador -->
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#CCCCCC"
            android:layout_marginTop="24dp"
            android:layout_marginBottom="24dp" />

        <!-- Configuraciones -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Configuraciones"
            android:textSize="18sp"
            android:textStyle="bold"
            android:layout_marginBottom="16dp" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_vertical">

            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Modo Oscuro"
                android:textSize="16sp" />

            <Switch
                android:id="@+id/switchDarkMode"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:layout_marginTop="16dp">

            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Notificaciones"
                android:textSize="16sp" />

            <Switch
                android:id="@+id/switchNotifications"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

        </LinearLayout>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Idioma"
            android:textSize="16sp"
            android:layout_marginTop="24dp"
            android:layout_marginBottom="8dp" />

        <Spinner
            android:id="@+id/spinnerLanguage"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="12dp" />

        <!-- Separador -->
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#CCCCCC"
            android:layout_marginTop="24dp"
            android:layout_marginBottom="24dp" />

        <!-- Información almacenada -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Datos Almacenados"
            android:textSize="18sp"
            android:textStyle="bold"
            android:layout_marginBottom="16dp" />

        <TextView
            android:id="@+id/txtStoredData"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="No hay datos almacenados"
            android:padding="16dp"
            android:background="#F5F5F5"
            android:textSize="14sp" />

        <!-- Botones de acción -->
        <Button
            android:id="@+id/btnLogout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Cerrar Sesión"
            android:backgroundTint="#FF9800"
            android:layout_marginTop="24dp" />

        <Button
            android:id="@+id/btnClearAll"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Limpiar Todo"
            android:backgroundTint="#F44336"
            android:layout_marginTop="8dp" />

    </LinearLayout>

</ScrollView>

🟩 6. Crear Drawable para EditText

📄 res/drawable/edittext_background.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#FFFFFF" />
    <corners android:radius="8dp" />
    <stroke android:width="1dp" android:color="#CCCCCC" />
    <padding android:left="12dp" android:top="12dp" 
             android:right="12dp" android:bottom="12dp" />
</shape>

🟩 7. MainActivity

📄 MainActivity.java

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    EditText txtUserName, txtEmail;
    Switch switchDarkMode, switchNotifications;
    Spinner spinnerLanguage;
    TextView txtStoredData;
    Button btnSave, btnLoad, btnLogout, btnClearAll;

    SharedPreferencesManager prefsManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        prefsManager = new SharedPreferencesManager(this);

        initializeViews();
        setupLanguageSpinner();
        loadStoredData();
        setupListeners();
    }

    private void initializeViews() {
        txtUserName = findViewById(R.id.txtUserName);
        txtEmail = findViewById(R.id.txtEmail);
        switchDarkMode = findViewById(R.id.switchDarkMode);
        switchNotifications = findViewById(R.id.switchNotifications);
        spinnerLanguage = findViewById(R.id.spinnerLanguage);
        txtStoredData = findViewById(R.id.txtStoredData);
        btnSave = findViewById(R.id.btnSave);
        btnLoad = findViewById(R.id.btnLoad);
        btnLogout = findViewById(R.id.btnLogout);
        btnClearAll = findViewById(R.id.btnClearAll);
    }

    private void setupLanguageSpinner() {
        String[] languages = {"Español", "English", "Português", "Français"};
        ArrayAdapter<String> adapter = new ArrayAdapter<>(
            this, 
            android.R.layout.simple_spinner_item, 
            languages
        );
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinnerLanguage.setAdapter(adapter);

        // Cargar idioma guardado
        String savedLanguage = prefsManager.getLanguage();
        int position = getLanguagePosition(savedLanguage);
        spinnerLanguage.setSelection(position);
    }

    private int getLanguagePosition(String language) {
        switch (language) {
            case "es": return 0;
            case "en": return 1;
            case "pt": return 2;
            case "fr": return 3;
            default: return 0;
        }
    }

    private String getLanguageCode(int position) {
        switch (position) {
            case 0: return "es";
            case 1: return "en";
            case 2: return "pt";
            case 3: return "fr";
            default: return "es";
        }
    }

    private void loadStoredData() {
        // Cargar switches
        switchDarkMode.setChecked(prefsManager.isDarkMode());
        switchNotifications.setChecked(prefsManager.isNotificationsEnabled());

        // Mostrar datos almacenados
        displayStoredData();
    }

    private void setupListeners() {
        // Botón Guardar
        btnSave.setOnClickListener(v -> saveUserData());

        // Botón Cargar
        btnLoad.setOnClickListener(v -> loadUserData());

        // Switch Modo Oscuro
        switchDarkMode.setOnCheckedChangeListener((buttonView, isChecked) -> {
            prefsManager.setDarkMode(isChecked);
            Toast.makeText(this, 
                "Modo oscuro: " + (isChecked ? "Activado" : "Desactivado"), 
                Toast.LENGTH_SHORT).show();
            displayStoredData();
        });

        // Switch Notificaciones
        switchNotifications.setOnCheckedChangeListener((buttonView, isChecked) -> {
            prefsManager.setNotifications(isChecked);
            Toast.makeText(this, 
                "Notificaciones: " + (isChecked ? "Activadas" : "Desactivadas"), 
                Toast.LENGTH_SHORT).show();
            displayStoredData();
        });

        // Spinner Idioma
        spinnerLanguage.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                String languageCode = getLanguageCode(position);
                prefsManager.setLanguage(languageCode);
                displayStoredData();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {}
        });

        // Botón Cerrar Sesión
        btnLogout.setOnClickListener(v -> logout());

        // Botón Limpiar Todo
        btnClearAll.setOnClickListener(v -> clearAllData());
    }

    private void saveUserData() {
        String userName = txtUserName.getText().toString().trim();
        String email = txtEmail.getText().toString().trim();

        if (userName.isEmpty() || email.isEmpty()) {
            Toast.makeText(this, "Completa todos los campos", Toast.LENGTH_SHORT).show();
            return;
        }

        // Guardar datos (simulando ID de usuario)
        int userId = (int) (Math.random() * 1000);
        prefsManager.saveLoginData(userName, email, userId);

        Toast.makeText(this, "Datos guardados exitosamente", Toast.LENGTH_SHORT).show();
        
        // Limpiar campos
        txtUserName.setText("");
        txtEmail.setText("");

        displayStoredData();
    }

    private void loadUserData() {
        if (!prefsManager.isLoggedIn()) {
            Toast.makeText(this, "No hay datos de usuario guardados", Toast.LENGTH_SHORT).show();
            return;
        }

        String userName = prefsManager.getUserName();
        String email = prefsManager.getUserEmail();

        txtUserName.setText(userName);
        txtEmail.setText(email);

        Toast.makeText(this, "Datos cargados", Toast.LENGTH_SHORT).show();
    }

    private void displayStoredData() {
        StringBuilder data = new StringBuilder();

        if (prefsManager.isLoggedIn()) {
            data.append("👤 Usuario Logueado\n\n");
            data.append("Nombre: ").append(prefsManager.getUserName()).append("\n");
            data.append("Email: ").append(prefsManager.getUserEmail()).append("\n");
            data.append("ID: ").append(prefsManager.getUserId()).append("\n\n");
        } else {
            data.append("❌ No hay sesión activa\n\n");
        }

        data.append("⚙️ Configuraciones:\n\n");
        data.append("Modo Oscuro: ").append(prefsManager.isDarkMode() ? "✓" : "✗").append("\n");
        data.append("Notificaciones: ").append(prefsManager.isNotificationsEnabled() ? "✓" : "✗").append("\n");
        data.append("Idioma: ").append(prefsManager.getLanguage()).append("\n");
        data.append("Primera Vez: ").append(prefsManager.isFirstTime() ? "Sí" : "No").append("\n");

        txtStoredData.setText(data.toString());
    }

    private void logout() {
        prefsManager.logout();
        txtUserName.setText("");
        txtEmail.setText("");
        displayStoredData();
        Toast.makeText(this, "Sesión cerrada", Toast.LENGTH_SHORT).show();
    }

    private void clearAllData() {
        prefsManager.clearAll();
        txtUserName.setText("");
        txtEmail.setText("");
        switchDarkMode.setChecked(false);
        switchNotifications.setChecked(true);
        spinnerLanguage.setSelection(0);
        displayStoredData();
        Toast.makeText(this, "Todos los datos eliminados", Toast.LENGTH_SHORT).show();
    }
}

🟩 8. Ejemplo de Uso Directo

// Guardar datos
SharedPreferences prefs = getSharedPreferences("MiApp", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("nombre", "Juan");
editor.putInt("edad", 25);
editor.putBoolean("premium", true);
editor.apply(); // o editor.commit()

// Leer datos
String nombre = prefs.getString("nombre", "");
int edad = prefs.getInt("edad", 0);
boolean premium = prefs.getBoolean("premium", false);

// Eliminar un dato
editor.remove("nombre");
editor.apply();

// Limpiar todo
editor.clear();
editor.apply();

🟩 9. Diferencia entre apply() y commit()

MétodoDescripción
apply()Asíncrono, más rápido, no retorna valor
commit()Síncrono, bloquea thread, retorna boolean

🟩 10. Métodos Principales

MétodoDescripción
putString()Guarda String
putInt()Guarda int
putBoolean()Guarda boolean
getString()Lee String
getInt()Lee int
getBoolean()Lee boolean
remove()Elimina clave
clear()Elimina todo
contains()Verifica si existe

▶️ Cómo Ejecutar

  1. Abre Android Studio
  2. Presiona Run
  3. Guarda datos y cierra la app
  4. Ábrela nuevamente y verifica que los datos persisten

🧪 Resultado Final

Aplicación que guarda preferencias, configuraciones de usuario y mantiene sesión activa incluso después de cerrar la app.

📥 Descargar Proyecto

👉 

🙌 Gracias por Visitar mi Blog

✔️ Compártelo
✔️ Déjame un comentario
✔️ Sígueme para más contenido

❓ Preguntas Frecuentes

1. ¿Qué es SharedPreferences?
Sistema de almacenamiento local en formato clave-valor para datos pequeños y configuraciones.

2. ¿Es seguro para contraseñas?
No. Para datos sensibles usa EncryptedSharedPreferences o Room Database.

3. ¿Cuándo usar apply() o commit()?
Usa apply() generalmente (más rápido). Usa commit() solo si necesitas el resultado booleano.

4. ¿Dónde se guardan los datos?
En archivos XML en /data/data/paquete/shared_prefs/

No hay comentarios:

Publicar un comentario