Login usuario simple para Android

Siguiendo con los tutos de Android que comencé ayer, esta vez vamos a crear un login de usuario simplecito enviando datos por POST a un servidor, y recibiendo un JSON como respuesta, la cual mostramos con un mensaje Toast🙂 Algo así

Login Activity

Lo primero entonces es crear el esqueleto del login. Lo hice en una tabla, con 2 textview, 2 edittexts y 1 botón. El código es así:

<?xml version="1.0" encoding="utf-8"?>
    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:stretchColumns="1">
        <TableRow>
            <TextView android:text="Usuario: "
                android:id="@+id/TextView01"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
            </TextView>
            <EditText android:text=""
                android:id="@+id/txtUsername"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content">
            </EditText>
        </TableRow>
        <TableRow>
            <TextView android:text="Contraseña: "
                android:id="@+id/TextView02"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
            </TextView>
            <EditText android:text=""
                android:id="@+id/txtPass"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:password="true">
            </EditText>
        </TableRow>
        <TableRow>
            <Button android:text="Conectar"
                android:id="@+id/btnLogin"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content">
            </Button>
        </TableRow>
    </TableLayout> 

Ahora que tenemos el esqueleto, vamos a nuestra clase Activity principal. Primero los imports que se usarán (son bastantes…):

package marcoTablet.Android;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import android.util.Log;

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.HttpResponse;

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;

import java.util.List;
import java.util.ArrayList;

import java.io.UnsupportedEncodingException;
import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;

import java.lang.IllegalStateException;
import java.lang.StringBuilder;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

En el onCreate solamente creo objetos para retener los controles, y al botón le asigno el evento click para empezar el logueo.

     public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        txtUsername = (EditText)this.findViewById(R.id.txtUsername);
        txtPass = (EditText)this.findViewById(R.id.txtPass);
        btnLogin = (Button)this.findViewById(R.id.btnLogin);
        btnLogin.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v){
                validar(txtUsername.getText().toString(), txtPass.getText().toString());
            }
        });
    }

Ahora, vamos a la función validar que recibe el nombre de usuario y su contraseña, y devuelve un boolean para ver si estamos bien o no.

private boolean validar(String username, String pass){
        /* Comprobamos que no venga alguno en blanco. */
        if (!username.equals("") && !pass.equals("")){
            /* Creamos el objeto cliente que realiza la petición al servidor */
            HttpClient cliente = new DefaultHttpClient();
            /* Definimos la ruta al servidor. En mi caso, es un servlet. */
            HttpPost post = new HttpPost("http://192.168.0.142:8080/marcoWeb/Login");

            try{
                /* Defino los parámetros que enviaré. Primero el nombre del parámetro, seguido por el valor. Es lo mismo que hacer un
                 http://192.168.0.142:8080/marcoWeb/Login?username=mario&pass=maritoPass&convertir=no */
                List<NameValuePair> nvp = new ArrayList<NameValuePair>(2);
                nvp.add(new BasicNameValuePair("username", username));
                /* Encripto la contraseña en MD5. Definición más abajo */
                nvp.add(new BasicNameValuePair("pass", toMd5(pass)));
                nvp.add(new BasicNameValuePair("convertir", "no"));
                /* Agrego los parámetros a la petición */
                post.setEntity(new UrlEncodedFormEntity(nvp));
                /* Ejecuto la petición, y guardo la respuesta */
                HttpResponse respuesta = cliente.execute(post);

                try{
                    /* Traspaso la respuesta del servidor (que viene como JSON) a la instancia de JSONObject en job.
                     /* Definición de inputStreamToString() más abajo. */
                    JSONObject job = new JSONObject(this.inputStreamToString(respuesta.getEntity().getContent()).toString());
                    /* Nuevo objeto, que contiene el valor para mensaje (definido en el JSON que crea el servidor */
                    JSONObject mensaje = job.getJSONObject("mensaje");
                    /* Muestro la respuesta */
                    Toast.makeText(Login.this, mensaje.getString("Estado"), Toast.LENGTH_LONG).show();
                    /* Abajo todas los exceptions que pueden ocurrir. Se imprimen en el log */
                    return true;
                }catch(JSONException ex){
                    Log.w("Aviso", ex.toString());
                    return false;
                }
            }catch(ClientProtocolException ex){
                Log.w("ClientProtocolException", ex.toString());
                return false;
            }catch(UnsupportedEncodingException ex){
                Log.w("UnsupportedEncodingException", ex.toString());
                return false;
            }catch(IOException ex){
                Log.w("IOException", ex.toString());
                return false;
            }
            catch(IllegalStateException ex){
                Log.w("IOException", ex.toString());
                return false;
            }
        }else{
            Toast.makeText(Login.this, "Campo vac'io !",
                            Toast.LENGTH_LONG).show();
            return false;
        }
    }

La respuesta del servidor es así:
Login OK:

{"mensaje": {"Estado": "OK", "Unidad": "Pintura", "CodUnidad": 5}}

Login MAL

{"mensaje": {"Estado": "ERROR", "Mensaje": "Pass incorrecta."}}

La forma de leer los datos de la BD y el traspaso a JSON no lo escribiré, ya que no viene al caso. Solo decir que la cabecera debe ser (en caso de un servidor java) de esta manera

response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");

Ahora, para traspasar la respuesta del servidor(que viene como dirección de memoria)hasta el objeto JSON primero la leemos, la pasamos a string, y luego la devolvemos. Con la función inputStreamToString

private StringBuilder inputStreamToString(InputStream is) {
        String line = "";
        StringBuilder total = new StringBuilder();
        //Guardamos la dirección en un buffer de lectura
        BufferedReader rd = new BufferedReader(new InputStreamReader(is));

        //Y la leemos toda hasta el final
        try{
            while ((line = rd.readLine()) != null) {
                total.append(line);
            }
        }catch(IOException ex){
            Log.w("Aviso", ex.toString());
        }

        // Devolvemos todo lo leido
        return total;
    }

Por último, la función para convertir la contraseña a MD5.

private String toMd5(String pass){
        try{
            //Creando Hash MD5
            MessageDigest digest = MessageDigest.getInstance("MD5");
            digest.update(pass.getBytes());
            byte messageDigest[] = digest.digest();

            //Creando Hex String
            StringBuffer hexString = new StringBuffer();
            for(int i=0; i<messageDigest.length; i++)
                hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
            Log.w("Pass en MD5: ", hexString.toString());
            return hexString.toString();
        }catch(NoSuchAlgorithmException ex){
            Log.w("NoSuchAlgorithmException", ex.toString());
            return null;
        }
    }

Agregar que esto no funcionará a menos que le demos permiso a la aplicación para que puede conectarse a internet. Para eso vamos al archivo androidmanifest.xml y agregamos la siguiente línea antes de la etiqueta de application.

<uses-permission android:name="android.permission.INTERNET" /> 

Y eso es todo. Para ver el log en el que estamos guardando mensajes vamos a la carpeta tools del SDK y ejecutamos ./adb logcat (puede estar bajo platform-tools)😀

Acerca de MaritoCares

Ingeniero Informático. Con tendencias a la programación en [C#, VB].NET, Java(Web principalmente...), PHP, JavaScript, algo mínimo de [ruby, python], y el clásico C.
Esta entrada fue publicada en Android, Java, Tutoriales y etiquetada , , . Guarda el enlace permanente.

20 respuestas a Login usuario simple para Android

  1. Ronny dijo:

    hola, excelente tuto, pero quisiera saber si tienes un ejemplo de como interpetrar una array de array :S??

    Saludos

    • MaritoCares dijo:

      Hola!

      Los Arrays de Arrays (en java supongo) son algo así:

      ArrayList<ArrayList<String>> AdA = new ArrayList<ArrayList<String>>();
      ArrayList<String> A = new ArrayList<String>();
      ArrayList<String> B = new ArrayList<String>();
      
      //Llenas el Array normal A
      // No recuerdo si es put o add
      A.add ("Valor 1 Array Normal");
      A.add ("Valor 2 Array Normal");
      A.add ("Valor 3 Array Normal");
      
      //Llenas el Array normal B
      B.add ("Valor 1 Array Normal B");
      B.add ("Valor 2 Array Normal B");
      B.add ("Valor 3 Array Normal B");
      
      //Luego el Array de Arrays
      AdA.add(A);
      AdA.add(B);
      
      //Si a esto le haces un .toString();
      //Tienes algo as'i [["Valor 1 Array Normal", "Valor 2 Array Normal", "Valor 3 Array Normal"], ["Valor 1 Array Normal B", "Valor 2 Array Normal B", "Valor 3 Array Normal B"]]
      
      //Ahora, para usarlos lo haces un con for:each o usando iteradores
      
      for (ArrayList<String> tmp : AdA){
         System.out.println(tmp.toString());
      }
      
      
  2. Alan dijo:

    hola me parece un blog muy bueno, soy nuevo, bastante nuevo programando en android, podrias en algun momento levantar un tutorial dirigido para los que estamos en cero absoluto!, los blog anteriores de instalacion y demas sin problemas! pero este me quede por la mitad, ya que en no estoy entendiendo en que archivo se deben escribir algunas porciones del codigo que has escrito.!
    Desde ya gracias

  3. Mario dijo:

    hola que tal, oye y como se comprueba si los datos del usuario son correctos o no???

  4. Manuel dijo:

    Hola! Felicidades por el blog, esta muy bueno!
    soy nuevo en esto y quiero hacerte una consulta que a lo mejor le ayuda a alguien mas, te planteo el escenario:

    Inicio sesión y guardo los datos en la BD del teléfono y redirecciono a pantalla principal.
    Para verificar si la sesión esta activa solo verifico que la tabla sesión tenga datos.
    Tengo un botón cerrar sesión, que al hacer clic me borra el contenido de la tabla y me manda a la pantalla de loguin.. PERO si presiono el botón (fisico) atrás vuelvo a la pantalla anterior que tienen el metodo VerificarSesion() en el onCreate y deberia devolverme al loguin pero no lo hace.. existe un metodo onShow, onDisplay o algo asi donde deba verificar la sesion ademas del onCreate? Mil gracias!

  5. Nicolas dijo:

    hola exelente aporte estoy comenzando con uno muu parecido a este pero es con sqlite solo necesito que se cre el usuario con su contraseña y lo permita logiar pero la verdad estoy reconfundido algun aporte te lo agradeceria

  6. uge dijo:

    Hola ¿podrías poner un ejemplo de como tienes el servlet?.

    Un saludo.

    • MaritoCares dijo:

      Hola !
      La verdad es que no tengo el código a la mano… pero es un servlet normal que, teniendo el nombre de usuario y la contraseña, las compara en relación a lo que esté guardado en la BD.

  7. jk dijo:

    tendras el proyecto completo de casualidad?, lo que sucede esque programo una aplicacion de android y no se bien android y es para dentro de dos dias, agradeceria tu ayuda

  8. Miguel dijo:

    buen Código, gracias.
    Creo que sería necesario alli incluir la funciòn en donde se hace el llamado de datos dentro de un hilo de ejecución, con esto no tendríamos problemas de que la aplicación se detenga.

  9. Eduardo dijo:

    una pregunta, la servlet la escribes en el mismo programa, o lo haces separado(en diferente clase, o en otro programa)??

  10. Alexis dijo:

    Muy buen tutorial, pero me da error en crear los objetossabes como lo puedo solucionar. Muchas gracias

  11. Sergio A A dijo:

    Hola amigo, disculpa, tienes el conocimiento de como desarrollar un visor para .shp o similar para android.
    Gracias

  12. Jorge Luis dijo:

    Amigo todas las librerias org.apache. ya estan obsoletas, alguna otra forma de hacerlo?

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s