El objetivo de este tutorial es implementar de forma
sencilla un mecanismo de protección para nuestra aplicación, creando una ventana de “Login” con un nombre de usuario y una
contraseña. Esta dialogo de Login también podrá ser usado o para proteger cualquier opción de menú de la aplicación
- Desarrollaremos el tutorial para un TABLET con la versión 4.0 del SDK de Android (Ice Cream Sandwich). Válido también para Android 2.x y 3.x.
- Veremos cómo trabajar con las opciones de MENU de la barra de tareas. Y también con las PREFERENCES.
- Pondremos por defecto unas credenciales para acceder a las “Preferences” (usuario, contraseña), para comenzar a trabajar y después las podremos cambiarlas.
- Mostraremos el contenido de las PREFERNCES, en el lugar de su descripción, cosa que no hace Android por defecto.
- Veremos como añadir por código objetos (Layouts, TextView y EditText) a un AlertDialog, usando la propiedad Buider del AlertDialog.
1.- Lo primero es crear un proyecto nuevo, ya sea con Eclipse o IntelliJ IDEA, utilizaremos la versión 4 del SDK de Android (Ice CreamSandwich).
Para este tutorial vamos a utilizar IntelliJ IDEA 11.1. Después de crear el proyecto tendríamos algo parecido a esto:
2.- Creación de un Menú para acceder a las Preferences de Android.
Comenzaremos con la creación de un menú para poder acceder a
las PREFERENCES, para ello crearemos una nueva carpeta en nuestro proyecto
dentro “res” llamada menu y dentro creamos el archivo menu.xml
con el siguiente contenido:
Insertar en el archivo de recursos “res\values\strings.xml” las siguientes líneas con el valor de las etiquetas del menú:
Nos quedaría el proyecto de la siguiente forma con nuestro menu.xml:Settings... Login Settings
Después nos
vamos a la clase asociada a nuestra actividad principal (MyActivity) “src\com.movalink.LoginTutorial\MainActivity” para incluir el siguiente
procedimiento que hace un Override del existente.
@Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuInflater menuInflater = getMenuInflater(); menuInflater.inflate(R.menu.menu, menu); return true; }
Lanzamos un
Emulador creado con la versión 4.0 de Android (Ice Cream Sandwich).
Ahora
ejecutamos la aplicación para que corra en el Emulador y vemos que en la
esquina superior derecha aparece un botón con tres puntos verticales, es la
opción de menú por defecto que nos muestra Android. Si pulsamos en ella vemos la
opción de menú que hemos creado.
3.- Trabajando con las Preferences.
El siguiente
paso, es crear dos campos en nuestras “Preferences” para poner el ellos el
nombre de usuario y la contraseña.
Lo primero
que debemos hacer es crear una carpeta en “res” con el nombre “xml” y dentro de ella
crearemos un archivo con formato XML llamado “settings.xml” al cual añadiremos
el siguiente contenido:
Las cadenas
de caracteres usadas en este archivo ej. "@string/username_settings_title", las declaramos con su valor en “res\values\strings.xml”:
Nombre de usuario Teclee el nombre de usuario Nombre de usuario Contraseña Teclee la contraseña Contraseña
A continuación crearemos la clase para manipular las “Preferences”, lo podemos hacer con clic derecho en com.movalink.LoginTutorial , en el menú contextual vamos a “New” y pulsamos “Android Component”
En la
carpeta ““src\com.movalink.LoginTutorial\” creamos una Activity y la llamamos
Preferences, que a su vez va a heredar de PreferenceActivity (Cambiamos
Activity por PreferenceActivity) e implementar el método SharedPreferences.OnSharedPreferenceChangeListener.
4.- Mostrando el contenido de las Preferences.
Si pulsamos, por ejemplo Nombre de Usuario, nos aparece un dialogo para introducir la información correspondiente.
Nuestra clase “Preferences.java” quedaría de la siguiente manera:
package com.movalink.LoginTutorial; import android.content.SharedPreferences; import android.preference.PreferenceActivity; public class Preferences extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener { //En el método onCreate de la Activity hacemos referencia a nuestro archivo de settings.xml public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.settings); public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { //To change body of implemented methods use File | Settings | File Templates. } }
A continuación crearemos dos constantes estáticas a nuestra clase
private static final String USERNAME_SETTINGS ="USERNAME_SETTINGS"; private static final String USERNAME_SETTINGS_DEFAULT = "admin"; private static final String PASSWORD_SETTINGS = "PASSWORD_SETTINGS"; private static final String PASSWORD_SETTINGS_DEFAULT ="1234";
Nota: Tener en cuenta que el
nombre de estas constantes es el mismo que “android:key="USERNAME_SETTINGS"” en
el archivo “settings.xml”
Como se puede observar los valores por defecto son
Username: admin
Password: 1234
Ahora crearemos dos métodos públicos para poder leer el nombre de
usuario y la contraseña que pondremos en las “Preferences”.
public static String getUsernameSettingsValue(Context context) { return PreferenceManager.getDefaultSharedPreferences(context). getString(USERNAME_SETTINGS, USERNAME_SETTINGS_DEFAULT); } public static String getPasswordSettingsValue(Context context) { return PreferenceManager.getDefaultSharedPreferences(context). getString(PASSWORD_SETTINGS, PASSWORD_SETTINGS_DEFAULT); }
Ahora regresamos a nuestra actividad principal MainActivity, para sobrescribir
el método que nos permite capturar el evento de selección de las
opciones de Menu, en nuestro caso solo hemos creado la opción de Settings para
acceder a las “Preferences”. Como podemos ver al seleccionar Settings lo que
hacemos es llamar a la Acividad Prferences a través de su clase.
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.settings: startActivity(new Intent(getApplicationContext(), Preferences.class)); return true; } return false; }
Hasta el momento nuestro Actividad principal (MyActivity), quedaría de la siguiente manera:
package com.movalink.LoginTutorial; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; public class MyActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuInflater menuInflater = getMenuInflater(); menuInflater.inflate(R.menu.menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.settings: startActivity(new Intent(getApplicationContext(), Preferences.class)); return true; } return false; } }
4.- Mostrando el contenido de las Preferences.
Ahora ejecutamos la aplicación para que corra en el Emulador, en la esquina superior derecha pulsamos el botón
de menú por defecto que nos muestra Android con nuestros “Settings”, y vemos
una nueva ventana con los dos parámetros que hemos creados, Nombre de Usuario y
Contraseña.
Si pulsamos, por ejemplo Nombre de Usuario, nos aparece un dialogo para introducir la información correspondiente.
Tecleamos Nombre de Usuario: movalink, y pulsamos OK, como podemos
observar no se muestra la información, de momento solo es posible si volvemos a
pulsar en las preferences el Nombre de Usuario.
Con la contraseña hacemos el mismo proceso y tecleamos Contraseña: 1234
Como mostrar el contenido de nuestras Preferences.
Para mostrar en el lugar de la descripción el contenido de las
Preferecias, crearemos un par de métodos que nos ayudaran.
En nuestra clase “Preferences” adicionamos los siguientes métodos
privados
/** * Set the summaries of all preferences */ private void initSummaries(PreferenceGroup pg) { for (int i = 0; i < pg.getPreferenceCount(); ++i) { Preference p = pg.getPreference(i); if (p instanceof PreferenceGroup) this.initSummaries((PreferenceGroup) p); // recursion else this.setSummary(p); } } /** * Set the summaries of the given preference */ private void setSummary(Preference pref) { // react on type or key if (pref instanceof ListPreference) { ListPreference listPref = (ListPreference) pref; pref.setSummary(listPref.getEntry()); } if (pref instanceof EditTextPreference) { EditTextPreference editPref = (EditTextPreference) pref; pref.setSummary(editPref.getText()); } }
Ahora en el método onCreate de la clase hacemos el llamado a estas dos
funciones, para asi mostrar en la descripción, el contenido de las Preferences.
this.initSummaries(this.getPreferenceScreen()); this.getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
package com.movalink.LoginTutorial; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.*; public class Preferences extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String USERNAME_SETTINGS = "USERNAME_SETTINGS"; private static final String USERNAME_SETTINGS_DEFAULT = "admin"; private static final String PASSWORD_SETTINGS = "PASSWORD_SETTINGS"; private static final String PASSWORD_SETTINGS_DEFAULT = "1234"; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.settings); this.initSummaries(this.getPreferenceScreen()); this.getPreferenceScreen().getSharedPreferences() .registerOnSharedPreferenceChangeListener(this); } /** * Set the summaries of all preferences */ private void initSummaries(PreferenceGroup pg) { for (int i = 0; i < pg.getPreferenceCount(); ++i) { Preference p = pg.getPreference(i); if (p instanceof PreferenceGroup) this.initSummaries((PreferenceGroup) p); // recursion else this.setSummary(p); } } /** * Set the summaries of the given preference */ private void setSummary(Preference pref) { // react on type or key if (pref instanceof ListPreference) { ListPreference listPref = (ListPreference) pref; pref.setSummary(listPref.getEntry()); } if (pref instanceof EditTextPreference) { EditTextPreference editPref = (EditTextPreference) pref; pref.setSummary(editPref.getText()); } } public static String getUsernameSettingsValue(Context context) { return PreferenceManager.getDefaultSharedPreferences(context). getString(USERNAME_SETTINGS, USERNAME_SETTINGS_DEFAULT); } public static String getPasswordSettingsValue(Context context) { return PreferenceManager.getDefaultSharedPreferences(context). getString(PASSWORD_SETTINGS, PASSWORD_SETTINGS_DEFAULT); } public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { //To change body of implemented methods use File | Settings | File Templates. } }
5.- Iniciar la Aplicación con el diálogo de Usuario y Contraseña.
Una vez creadas nuestras credenciales en las “Preferences”, es el
momento de comenzar a usarlas.
La idea es que cuando arranque nuestra aplicación nos muestre un
dialogo con Usuario y Contraseña, para poder acceder a la misma.
Lo primero que haremos es crear las siguientes constantes y variables
privadas en nuestra actividad principal (MyActivity):
Estas constantes son para validar de acceso y almacenar el contenido de nuestras Preferences.
private static final int LOGIN_ACTION = 0; private static final int SETTINGS_ACTION = 1; private boolean validUser = false; private String userNamePreferences; private String passwordPreferences;
A continuación hacemos un override del método onStart(), y es aquí donde obtendremos los valores guardados en las “Preferences”. Llamaremos a la función que nos muestra el Login, en este caso pasaremos la constante LOGIN_ACTION, ya que solo vamos a validar el usuario y la contraseña para acceder a la aplicación.
@Override protected void onStart(){ super.onStart(); if (!validUser){ userNamePreferences = Preferences.getUsernameSettingsValue(this); passwordPreferences = Preferences.getPasswordSettingsValue(this); //Esta es la función que nos muestra el diálogo de Login showAccessPopUpDialog(userNamePreferences, passwordPreferences, LOGIN_ACTION); } }
Este procedimiento showAccessPopUpDialog(…) nos permite proteger otras
opciones de menú de la aplicación. El procedimiento lo colocamos en muestra actividad principal (MyActivity).
Al final del tutorial se incluye el contenido de este procedimiento con todo los comentarios explicativos.
6.- Protegiendo las Preferences con el diálogo de Usuario y Contraseña
Al final del tutorial se incluye el contenido de este procedimiento con todo los comentarios explicativos.
6.- Protegiendo las Preferences con el diálogo de Usuario y Contraseña
En el siguiente ejemplo vamos a proteger con usuario y contraseña el
acceso a las “Preferences”
Anteriormente se accedía directamente a las “Preferences” pulsando en
Settings…, como podemos ver hemos comentado el llamado directo y ahora utilizamos
showAccessPopUpDialog(userNamePreferences, passwordPreferences,
SETTINGS_ACTION);
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.settings: //startActivity(new Intent(getApplicationContext(), Preferences.class)); //Show popup dialog to permit access to preferences showAccessPopUpDialog(userNamePreferences, passwordPreferences, SETTINGS_ACTION); return true; } return false; }
A continuación mostramos el contenido de los procedimientos que hacen
posible el funcionamiento de nuestra LOGIN, ambos procedimientos debemos agregarlos a nuestra
actividad principal MyActivity. showAccessPopUpDialog(…) y loginAction(...)
Procedimiento: showAccessPopUpDialog(…)
showAccessPopUpDialog(final String userName, final String password, final int action) y loginAction(int action) private void showAccessPopUpDialog(final String userName, final String password, final int action) { final AlertDialog.Builder helpBuilder = new AlertDialog.Builder(this); helpBuilder.setTitle("Acceso a clientes"); helpBuilder.setMessage("Introduzca usario y contraseña"); helpBuilder.setIcon(R.drawable.key_stroke_32x32); //Creamos un TextView para la etiqueta Usuario final TextView LabelName = new TextView(this); LabelName.setWidth(100); LabelName.setText("Usuario:"); //Creamos un EditText para teclear el valor del campo Usuario final EditText inputName = new EditText(this); inputName.setSingleLine(); inputName.setWidth(150); inputName.setInputType(InputType.TYPE_CLASS_TEXT); inputName.setText(""); //Creamos un TextView para la etiqueta Contraseña final TextView LabelPass = new TextView(this); LabelPass.setWidth(100); LabelPass.setText("Contraseña:"); //Creamos un EditText para teclear el valor del campo Contraseña final EditText inputPass = new EditText(this); inputPass.setSingleLine(); inputPass.setWidth(150); inputPass.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); inputPass.setText(""); //Definimos parametros para luego aplicar al Layout LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); //Creamos un Layout comun para agrupar la entiqueta(TexView) y el campo (EditText) //Tanto del Usuario como de la Contraseña LinearLayout layout = new LinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); layout.setGravity(Gravity.CENTER_HORIZONTAL); layout.setPadding(10,5,0,5); //Creamos un Layout para agrupar la entiqueta(TexView) y el campo (EditText) // del Usuario LinearLayout layoutUser = new LinearLayout(this); // Aplicamos los parámetros del layout a nuestros objectos layoutUser.setLayoutParams(params); layoutUser.addView(LabelName); layoutUser.addView(inputName); //Creamos un Layout para agrupar la entiqueta(TexView) y el campo (EditText) //de la Contraseña LinearLayout layoutPass = new LinearLayout(this); // Aplicamos los parámetros del layout a nuestros objectos layoutPass.setLayoutParams(params); layoutPass.addView(LabelPass); layoutPass.addView(inputPass); //Adicionamos al LAyout comun los dos nuevos layouts // el del Usuario y el de la Contraseña, creados anteriormente layout.addView(layoutUser); layout.addView(layoutPass); //Adicionamos el layout comun al helpBuilder helpBuilder.setView(layout); helpBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // Do nothing but close the dialog String inputUserTxt = inputName.getText().toString(); String inputPasswordTxt = inputPass.getText().toString(); if (inputUserTxt.equals(userName) & inputPasswordTxt.equals(password)) { //Seleccionamos la acción a ejecutar loginAction(action); } else { Toast toast = Toast.makeText(getBaseContext(), "Usuario o Contraseña no válidos. Inténtelo otra vez", Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); // Si la contraseña o el usuario no son válidos volvemos a motrar el diálogo showAccessPopUpDialog(userNamePreferences,passwordPreferences,action); } } }); helpBuilder.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // Do nothing finish(); } }); // Crear el diálogo no lo muestra, hay que hacer el show() AlertDialog helpDialog = helpBuilder.create(); // Deshabilitar hacer click fuera del diálogo helpDialog.setCanceledOnTouchOutside(false); //Mostrar el diálogo helpDialog.show(); //Establecer ancho y alto helpDialog.getWindow().setLayout(400, 410); }Procedimiento: loginAction(...)
protected boolean loginAction(int action){ switch (action) { case LOGIN_ACTION: validUser = true; Toast toast = Toast.makeText(getBaseContext(), "USUARIO Y CONTRASEÑA CORRECTOS. (:", Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return true; case SETTINGS_ACTION: //Preferences access startActivity(new Intent(getApplicationContext(), Preferences.class)); return true; default: return false; } }Para descargar el código fuente de la aplicación: LoginTutorial
Recordar que para acceder por primera vez debe teclear
USUARIO: admin
CONTRASEÑA: 1234
No hay comentarios:
Publicar un comentario