El presente tutorial tiene como objetivo explicar cómo llevar a cabo la conexión a una base de datos MySQL desde una aplicación Android. La aplicación de ejemplo va a realizar algo bastante sencillo. Al introducir el nombre de una videoconsola y el nombre del juego, va a devolver su género, valoración, PEGI y su precio.
Para ello se ha de tener acceso y privilegios de administrador de una base de datos MYSQL, para lo que en este caso se va a utilizar XAMPP. Las siglas provienen de: X para cualquier sistema operativo, A de Apache, M de MySQL, P de PHP y P de Perl.
No se va a detallar en este tutorial la instalación de XAMPP, pero puede seguirse fácilmente aquí o aquí. XAMPP permite el uso del pc como servidor y además proporciona una base de datos MySQL que es justo lo que necesitamos.
Configuración de la base de datos
Figura 1. XAMPP Control Panel
Para poder entrar en el servidor sólo hay que poner en la barra de direcciones del buscador la dirección:
>> http://localhost:8080/xampp
Donde como sabéis localhost puede sustituirse por la dirección 127.0.0.1 y 8080 es el puerto correspondiente al servidor Apache .Podría ser otro en función de la configuración, por lo que es importante comprobar desde el panel de control qué puerto tiene asignado.
Figura 2. Página inicio XAMPP
En la figura 2 aparece marcado en un recuadro negro, justo debajo de tools, “phpMyAdmin”. Esta es la herramienta que permite configurar las diferentes bases de datos MySQL desde el entorno web. Por supuesto podría hacerse desde la consola, pero por simplicidad en este tutorial se va a usar phpMyAdmin.
Al pinchar en phpMyAdmin se accede a la página de configuración de bases de datos MySQL:
Figura 3. phpMyAdmin
Figura 4. Bases de datos phpMyAdmin
En donde aparece claramente una caja de texto para crear una nueva base de datos. Únicamente debemos especificar el nombre y darle a “Crear”. Dejamos por defecto el otro recuadro en “Cotejamiento”. El nombre de la base de datos de este ejemplo va a ser “videoconsolas”.
Al pinchar en “Crear” dirá que se ha creado correctamente. Ahora hay que configurarla. Pinchamos en la base de datos creada, en donde tendremos que crear una tabla por cada videoconsola que queramos tener en nuestra base de datos. En este caso se van a crear 2: New Nintendo3DS y Xbox360:
Figura 5. Creación de una tabla en la BD
Figura 6. Configuración de la tabla
La figura 6 muestra las 5 columnas y sus tipos y longitudes asociadas. Los campo “nombre” y “genero” serán de tipo VARCHAR (cadenas de longitud variable) mientras que “valoración” y “precio” son de tipo decimal (FLOAT) y por último PEGI de tipo INT. Es importante saber qué tipo de variable tiene asociada cada columna ya que más tarde llamaremos a un método u otro en función del tipo para acceder a la información. El resto de parámetros los dejamos por defecto y pinchamos en “Guardar”.
Lo siguiente es añadir un par de juegos con los que probar la aplicación. Desde la pestaña estructura podremos acceder ahora a la tabla. Al pinchar aparecerá un mensaje diciendo que MySQL ha devuelto un conjunto de valores vacío (lógico, aún no hemos agregado ningún juego). Para insertar una nueva entrada le damos a la pestaña “Insertar”, y llegaremos a la siguiente página:
Figura 7. Añadiendo una entrada a la tabla
En este caso se han añadido los juegos FIFA 15 y Monster Hunter 4. La figura 7 muestra cómo se puede añadir un juego, concretamente el FIFA 15. Sólo hay que indicar los valores y darle a “Continuar”. Ya se tiene el juego añadido a la tabla “new nintendo3ds” dentro de “videoconsolas”. Si ahora pinchamos en la pestaña “Examinar” aparecen las 2 entradas.
Después de esto ya se tendría la base de datos lista.
Acceso a la base de datos desde la aplicación
Ahora sí, ya estamos en condiciones de obtener información de la base de datos desde nuestra aplicación. Creamos el proyecto en Android Studio al que vamos a llamar “ejemploConexionBaseDatos”. Sólo nos va a hacer falta una clase, “MainActivity”. En cuanto al layout, está disponible junto con todo el proyecto en mi repositorio de GitHub que encontraréis al final del tutorial.
Lo que se va a utilizar para realizar a cabo la conexión con la base de datos es JDBC (Java DataBase Connectivity). Es una API que permite la ejecución de operaciones sobre bases de datos desde JAVA. Para más información acerca de la misma puedes hacer click aquí. Primero hay que descargarse el .jar correspondiente a la API desde su página.
Para cargar la librería en Android Studio vamos a Project > [aplicación] > libs y pegamos el .jar en ese directorio. Después tenemos que añadir la siguiente línea en Gradle Scripts > build.gradle (Module:app), en el apartado de dependencies:
>> compile files('mysql-connector-java-3.0.17-ga-bin.jar')
NOTA: Hay que poner el nombre de .jar descargado. En el momento de hacer este tutorial yo tenía la versión 3.0.17, pero esto puede cambiar (y de hecho ha cambiado) así es importante poner el nombre correctamente.
NOTA: Hay que poner el nombre de .jar descargado. En el momento de hacer este tutorial yo tenía la versión 3.0.17, pero esto puede cambiar (y de hecho ha cambiado) así es importante poner el nombre correctamente.
Una vez hecho esto ya podemos acceder a los métodos que nos hacen falta para realizar la conexión, pero eso será más tarde.
Lo primero que hacemos en el método OnCreate() es buscar las referencias de los elementos del layout previamente instanciados:
etNombre = (EditText)findViewById(R.id.etNombre);
etVideoconsola = (EditText)findViewById(R.id.etVideoconsola);
tvGenero = (TextView)findViewById(R.id.tvGenero);
tvValoracion = (TextView)findViewById(R.id.tvValoracion);
tvPEGI = (TextView)findViewById(R.id.tvPEGI);
tvPrecio = (TextView)findViewById(R.id.tvPrecio);
btnConectar = (Button)findViewById(R.id.btnConectar);
Además hay que añadir el listener al botón que realiza la petición sql:
btnConectar.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String videoconsola = etVideoconsola.getText().toString();
String juego = etNombre.getText().toString();
if (videoconsola.equals("New Nintendo3DS")){
videoconsola = "`" + videoconsola + "`";
}
new ConexionDB().execute(IP,baseDatos,videoconsola,juego);
}
});
Vamos por partes. Primero obtenemos el datos de la videoconsola y el juego elegido por el usuario. El condicional se utiliza porque, cuando se quiere hacer una petición SQL del tipo:
SELECT * FROM tabla
Si “tabla” contiene espacios debe ponerse entre comillas francesas `. Por lo tanto, cuando el usuario ponga “New Nintendo3DS” se le deben añadir las comillas, en otro caso saltará una excepción SQL. Quedaría tal que así:
SELECT * FROM `New Nintendo3DS`
Además, desde el main de la interfaz de usuario no se permiten conexiones a la red, hay que hacerlo desde fuera del MainThread. Es por esto que se ha creado la clase ConexionDB que extiende a Asyntask, de modo que la acción se lleve a cabo fuera. La clase es la siguiente:
public class ConexionDB extends AsyncTask<String,Void,ResultSet>{
@Override
protected ResultSet doInBackground(String... strings) {
try {
Connection conn;
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://"+strings[0]+strings[1], "root", "");
Statement estado = conn.createStatement();
System.out.println("Conexion establecida");
String peticion ="select * from " +strings[2]+" where nombre='"+strings[3]+"'";
ResultSet result = estado.executeQuery(peticion);
return result;
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(ResultSet result) {
try {
if (!result.next() ) {
System.out.println("No data");
}else{
tvGenero.setText(result.getString("genero"));
tvValoracion.setText(Float.toString(result.getFloat("valoracion")));
tvPEGI.setText(Integer.toString(result.getInt("PEGI")));
tvPrecio.setText(Float.toString(result.getFloat("precio")));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Para el que no sepa qué es la clase Asyntask y cómo funciona, puede verlo aquí. La clase ConexiónDB recibe como parámetros un vector de Strings, que le pasa como argumento a doInBackGround. Este método a su vez devuelve ResultSet a OnPostExecute que es de tipo void. Pero vamos al funcionamiento:
- En doInBackground realizamos la conexión con la base de datos. El método Class.forName() carga la clase que recibe como argumento si no ha sido cargada previamente. Después creamos la conexión mediante el método getConnection de DriverManager. Este método recibe como argumento un primer String con el siguiente formato:
jdbc:mysql://[IP]:[puerto]/[nombre base de datos]
En este caso sería:
jdbc:mysql://192.168.1.131:3306/videoconsolas
El segundo y tercer String hacen referencia al usuario y la contraseña para acceder a la base de datos. En este caso es el usuario y contraseña por defecto, “root” de usuario y nada (“ ”) de contraseña.
Lo siguiente es crear un “estado” que será el encargado de realizar la petición SQL. Esto se hace llamando al método createStatement() de la clase Connection.
Por último sólo queda formular la petición SQL en función de los datos introducidos por el usuario y recibir los resultados. Para ello se crea una instancia de la clase ResultSet que contiene dichos resultados.
- En el método OnPostExecute recogemos los datos devueltos y seleccionamos los que nos interesen. ResultSet contiene un listado de filas que cumplen la condición nombre=’strings[3]’, es decir, que si el nombre de un juego sólo aparece una vez el número de filas de ResultSet va a ser 1. Sin embargo, si lo que queremos es hacer un recorrido por la base de datos y no seleccionamos ningún elemento (juego) en concreto, debemos ir recorriendo el listado de filas con el método next() de ResultSet. Este método cambia el puntero de una fila a otra, de manera que si lo ejecutamos tal que asi:
While(result.next()){
//codigo a ejecutar
}
Podemos ir recorriendo cada una de las filas para obtener los datos que se deseen.
Volviendo a la aplicación, en nuestro caso sólo se tiene 1 fila en ResultSet, por lo que lo único que debemos hacer es obtener los campos género, valoración, PEGI y precio llamando a:
result.getString() // result.getInt() //….etc
y añadirlos a los diferentes TextView. El resultado final es este:
Figura 8. Resultado
Consideraciones adicionales
1. Es necesario añadir permisos de conexión a internet en AndroidManifest para poder acceder a la base de datos. Para ello hay que añadir en ese documento la siguiente línea:
<uses-permission android:name="android.permission.INTERNET" />
2. Si se está utilizando XAMPP en una red de área local, primero hay que identificar cuál es la conexión IP del servidor. La mayoría de los routers utilizan el protocolo DHCP para proporcionar direcciones IP y NORMALMENTE asignan la misma dirección IP, dentro del rango del que disponen, cada vez que un equipo se conecta a dicha red. Sin embargo es muy posible que dicha dirección IP sea diferente si estas en una red diferente a la que habitualmente usas, por lo que es importante comprobarlo primero.
3. Relacionado con el punto 2, si se utiliza un servidor XAMPP tienes que estar conectado a la misma red Wi-Fi que el servidor. Si, por ejemplo, se intenta utilizar la aplicación de ejemplo con la conexión de datos del móvil (no Wi-Fi) no encontrará nunca el servidor XAMPP. Esto se debe a que al utilizar la conexión de datos se asigna un rango de direcciones IP, por parte del operador de turno, diferente del rango de direcciones IP de la red local WiFi, y la red del operador no sabe qué dirección es la 192.168.x.x ya que es un rango de direcciones privadas.
4. Es posible que al intentar realizar la conexión no permita acceder a la base de datos porque faltan privilegios. En ese caso hay que ir a XAMPP > phpMyAdmin > [basededatos] > privilegios y añadir permisos para acceder desde otro host diferente al servidor que está ejecutando XAMPP.
4. Es posible que al intentar realizar la conexión no permita acceder a la base de datos porque faltan privilegios. En ese caso hay que ir a XAMPP > phpMyAdmin > [basededatos] > privilegios y añadir permisos para acceder desde otro host diferente al servidor que está ejecutando XAMPP.
El código y la aplicación de ejemplo pueden descargarse desde el siguiente repositorio de GitHub: repositorio GitHub