Añadiendo preferencias de usuario

Android nos facilita la configuración de nuestros programas, al permitir añadir una lista de preferencias que el usuario podrá modificar. Por ejemplo, el usuario podrá indicar con que frecuencia la aplicación ha de sincronizarse con el servidor o si queremos que se lancen notificaciones. Las preferencias también pueden utilizarse para que tu aplicación almacene información de forma permanente. En el capítulo 9 se estudiará cómo realizar esta función.
 

video[TutorialAñadir preferencias en Android

NOTA: A continuación se proponen una serie de ejercicios para añadir preferencias en Asteroides.  Para hacerlo en Mis Lugares puedes cambiarlos textos que aparecen, para que correspondan con la siguiente captura:

Ejercicio paso a paso: Añadiendo preferencias a Asteroides.

1.    Abre el proyecto Mis Lugares.

2.    Pulsa con el botón derecho sobre res y selecciona la opción New > Android resource file.

3.   Completa los campos File name: preferencias y Resource type: XML. Se creará el fichero res/xml/preferencias.xml.

4.    Edita este fichero. Selecciona la lengüeta Text  e introduce el siguiente código:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:key="preferencias_principal" >
    <CheckBoxPreference
        android:key="musica"
        android:title="Reproducir música"
        android:summary="Se reproduce música de fondo"/>
    <ListPreference
        android:key="graficos"
        android:title="Tipo de gráficos"
        android:summary="Se escoge la representación de gráficos"
        android:entries="@array/tiposGraficos"
        android:entryValues="@array/tiposGraficosValores"
        android:defaultValue="1"/>
    <EditTextPreference
        android:key="fragmentos"
        android:title="Número de Fragmentos"
        android:summary="En cuantos trozos se divide un asteroide"
        android:inputType="number"
        android:defaultValue="3"/>
</PreferenceScreen> 

El significado de cada etiqueta y atributo se descubre fácilmente si observas el resultado obtenido que se muestra a continuación. El atributo inputType permite configurar el tipo de teclado que se mostrará para introducir el valor. Coinciden con el atributo de EditText. Para ver los posibles valores consultar: developer.android.com/reference/android/widget/TextView.html#attr_android:inputType

5. Para almacenar los valores del desplegable, has de crear el fichero /res/values/arrays.xml con el siguiente contenido:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="tiposGraficos">
        <item>vectorial</item>
        <item>bitmap</item>
        <item>3D</item>
    </string-array>
    <string-array name="tiposGraficosValores">
        <item>0</item>
        <item>1</item>
        <item>2</item>
    </string-array>
</resources> 

6.     Crea ahora una nueva clase PreferenciasFragment con el siguiente código:

public class PreferenciasFragment extends PreferenceFragment {
   @Override public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      addPreferencesFromResource(R.xml.preferencias);
   }
} 
class PreferenciasFragment : PreferenceFragment() { //Deprecated
   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      addPreferencesFromResource(R.xml.preferencias)
   }
} 

Nota sobre Java/Kotlin: Pulsa Alt-Intro para que automáticamente se añadan los paquetes que faltan.

La clase PreferenceFragment permite crear un fragment que contiene una ventana con las opciones de preferencias definidas en un recurso XML. Un fragment es un elemento que puede ser incrustado dentro de una actividad. El uso de fragment se estudia con más detalle en la última unidad del curso.

7.     Ahora vamos a crear una actividad que simplemente muestre el fragment anterior. Crea la la clase PreferenciasActivity con el siguiente código:

public class PreferenciasActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getFragmentManager().beginTransaction()
                .replace(android.R.id.content, new PreferenciasFragment())
                .commit();
    }
} 
class PreferenciasActivity : Activity() {
   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      fragmentManager.beginTransaction()
         .replace(android.R.id.content, PreferenciasFragment())
         .commit()
   }
} 

Desde una actividad podemos visualizar un fragment en tiempo de ejecución. Para ello utilizamos el manejador de fragments de la activdad (getFragmentManager()) y comenzamos una transacción (beginTransaction()). Una transacción es una operación de insertado, borrado o reemplazo de fragments. En el ejemplo vamos a reemplazar el contenido de la actividad por un nuevo fragment de la clase PreferenciasFragment. Finalmente se llama a commit() para que se ejecute la transacción.

8.     No hay que olvidar registrar toda nueva actividad en AndroidManifest.xml.

9.     Añade a MainActivity.java el método lanzarPreferencias(). Este método ha de tener el mismo código que lanzarAcercaDe() pero lanzando la actividad PreferenciasActivity. Al pulsar el botón con texto “Preferencias” haz que se llame a lanzarPreferencias().

10.   Para activar la configuración desde la opción de menú añade el siguiente código en el fichero MainActivity.java en el método onOptionsItemSelected().

if  (id == R.id.action_settings) {
   lanzarPreferencias(null);
   return true;
} 
R.id.action_settings -> {
   lanzarPreferencias()
   true
} 

11.     Arranca la aplicación y verifica que puedes lanzar las preferencias mediante las dos alternativas.

Organizando preferencias

Cuando el número de preferencias es grande resulta interesante organizarlas de forma adecuada. Una posibilidad consiste en dividirlas en varias pantallas. De forma que cuando se seleccione una opción en la primera pantalla, se abra una nueva pantalla de preferencias. Para organizar las preferencias de esta forma usa el siguiente esquema:

<PreferenceScreen>
  <CheckBoxPreference …/>
  <EditTextPreference …/>
  …
  <PreferenceScreen android:title="Notificaiones por correo"> <CheckBoxPreference …/> <EditTextPreference …/> … </PreferenceScreen> </PreferenceScreen> 

Organizando preferencias

Cuando el número de preferencias es grande, resulta interesante organizarlas de forma adecuada. Una posibilidad consiste en dividirlas en varias pantallas, de forma que cuando se seleccione una opción en la primera pantalla, se abra una nueva pantalla de preferencias. Para organizar las preferencias de esta forma, usa el siguiente esquema:

<PreferenceScreen>
  <CheckBoxPreference …/>
  <EditTextPreference …/>
  …
  <PreferenceScreen android:title=”Modo multijugador”>
    <CheckBoxPreference …/>
    <EditTextPreference …/>
    …
  </PreferenceScreen>
</PreferenceScreen> 

Práctica: Organizando preferencias(I)

1. Crea una nueva lista de preferencias <PreferenceScreen> dentro de la lista de preferencias del fichero res/xml/preferencias.xml.
2. Asígnale al parámetro android:title el valor “Notificaciones por correo”.
3. Crea tres elementos dentro dentro de esta lista: Activar multijugador, Máximo de jugadores y Tipo de conexión. Para este último, han de poder escogerse los valores: Bluetooth, Wi-Fi e Internet.

Otra alternativa para organizar las preferencias consiste en agruparlas por categorías. Con esta opción se visualizarán en la misma pantalla, pero separadas por grupos. Has de seguir el siguiente esquema: 

Otra alternativa para organizar las preferencias consiste en agruparlas por categorías. Con esta opción se visualizarán en la misma pantalla, pero separadas por grupos. Has de seguir el siguiente esquema:

<PreferenceScreen>
  <CheckBoxPreference …/>
  <EditTextPreference …/>
  …
  <PreferenceCategory android:title=”Modo multijugador”>
    <CheckBoxPreference …/>
    <EditTextPreference …/>
.  . …
  </PreferenceCategory>
</PreferenceScreen> 

A continuación se representa la forma en la que Android muestra las categorías:

Práctica: Organizando preferencias(II)

Modifica la práctica anterior para que en lugar de mostrar las propiedades en dos pantallas, aparezcan en una sola, tal y como se muestra en la imagen anterior.

Como se almacenan las preferencias de usuario

Si un usuario modifica el valor de una preferencia, este quedará almacenado de forma permanente en el dispositivo. Para conseguir esta persistencia Android almacena las preferencias seleccionadas en un fichero XML dentro de la carpeta data/data/nombre.del.paquete/files/shared_prefs. Donde nombre.del.paquete ha de ser reemplazado por el paquete de la aplicación. El nombre del fichero para almacenar las preferencias de usuario ha de ser siempre nombre.del.paquete_preferences.xml.Esto significa que solo puede haber unas preferencias de usuario por aplicación. Como se estudiará en el capítulo 9 de El Gran Libro de Android pueden haber otros ficheros de preferencia, pero a diferencia de las preferencias de usuario no pueden ser editadas directamente por el usuario sino que hay que acceder a ellas por código.

Ejercicio paso a paso: Donde se almacenan las preferencias de usuario

Veamos donde se han almacenado las preferencias que acabamos de crear:

1.    Para navegar por el sistema de ficheros de un dispositivo, desde Android Studio, abre la opción Tools > Android > Android Device Monitor y selecciona la lengüeta File Explorer

2.    Busca el siguiente fichero:  /data/data/com.examples.mislugares/shared_prefs/ com.examples.mislugares_preferences.xml

NOTA: En un dispositivo real no tendrás permiso para acceder a estos ficheros (A menos que el dispositivo haya sido rooteado).

3. Haz doble clic sobre el fichero para visualizar su contenido:

 
<map>
   <boolean name="musica" value="true" /> 
   <string name="graficos">1</string> 
   <string name="fragmentos">3</string> 
</map>   

Accediendo a los valores de las preferencias

Por supuesto, será necesario acceder a los valores de las preferencias para alterar el funcionamiento de nuestra aplicación. El siguiente ejemplo nos muestra cómo realizarlo:

public void mostrarPreferencias(){
   SharedPreferences pref =
              PreferenceManager.getDefaultSharedPreferences(this);
   String s = "notificaciones: "+ pref.getBoolean("notificaciones",true)
              +", máximo a listar: " + pref.getString("maximo","?");
   Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
} 

El código comienza creando el objeto pref de la clase SharedPreferences y le asigna las preferencias definidas para la aplicación. A continuación crea el String s y le asigna los valores de dos de las  preferencias. Se utilizan los métodos pref.getBoolean() y pref.getString(), que disponen de dos parámetros: el valor de key que queremos buscar ("notificaciones" y "maximo") y el valor asignado por defecto en caso de no encontrar esta key.

Finalmente se visualiza el resultado utilizando la clase Toast. Los tres parámetros indicados son el contexto (nuestra actividad),  el String a mostrar y el tiempo que se estará mostrando esta información.

Ejercicio paso a paso: Accediendo a los valores de las preferencias

1. Copia la función anterior en la clase MainActivity. Añade el parámetro que se muestra a continuación  mostrarPreferencias(View view).

2. Asígnala al atributo onClick del botón Mostrar Lugares el método anterior.

3. Visualiza también el resto de las preferencias que hayas introducido.


Preguntas de repaso y reflexión: preferencias de usuario