En este video te explicamos en detalle todo el proceso para publicar una Aplicación Android…
Sincronización con MySQL: proyecto con Android Studio para Android 5.0
4.
Sincronización con MySQL: proyecto con Android Studio para Android 5.0
Generamos una nueva versión de la App Android de gestión de citas y reuniones de trabajo, realizándola con Android Studio para la versión Android 5.0 Lollipop.
Recordamos que este proyecto nos sirve de ejemplo para explicar detalladamente cómo realizar la conexión y sincronización de Android con un servidor externo de base de datos MySQL. Esta App nos permite insertar y consultar registros en una base de datos MySQL externa, creada previamente desde la propia aplicación Android.
Como siempre, tienes todo el código del proyecto para su descarga al final de este tutorial.
Elementos del proyecto
El proyecto se centrará en el proceso de conexión a la base de datos MySQL, y en cómo ejecutar una consulta INSERT desde un nuevo hilo de la aplicación. En primer lugar se enumeran los elementos que intervendrán en dicho proceso:
- Clase Citas, que hereda de la clase base ListActivity, dónde se define la lógica de conexión a la base de datos MySQL y evento de inserción de datos.
- Clase TareaAsincronaInsertar, que hereda de la clase base AsyncTask, dónde se realizará la conexión a la base de datos, y se ejecutará la sentencia INSERT con los datos introducidos por el usuario.
- Layout activity_citas, donde se implementarán un componente de tipo Button que lanzará el proceso de conexión e inserción de un registro, y cuatro componentes de tipo EditText que recogerán los datos para la nueva cita a almacenar.
- Librería ‘mysql-connector-java-5.1.31-bin.jar’ para implementar las funcionalidades asociadas a la lectura, escritura o eliminación de una base de datos MySQL.
Estructura del proyecto
Vemos en esta imagen la estructura del proyecto:
Documentación código fuente
Explicamos las diferentes clases y ficheros layout del proyecto, incluyendo la conexión y creación de la base de datos.
SincronizacionBD\app\src\main\java\com\academiaandroid\sincronizacionbd\Citas.java
Se define una clase llamada Citas, que hereda de la clase base ListActivity, dónde se lanzará el proceso de creación de una nueva cita en la agenda, con los datos introducidos por el usuario:
1 2 |
public class Citas extends ListActivity { |
Se declaran los componentes y clases necesarias para realizar consultas a una base de datos en MySQL:
1 2 |
private EditText edPassword,edNombre, edApellidos, edFecha, edDescripcion; |
Puesto que vamos a trabajar con la librería de mysql es conveniente que tengamos en cuenta la documentación donde se habla de las clases que vamos a usar de la misma: ResultSet y Statement
Documentación oficial java.sql.ResultSet
Documentación oficial java.sql.Statement
Se enlazan dichos componentes con sus recursos a nivel de layout:
1 2 3 4 5 |
edNombre = (EditText)findViewById(R.id.edNombre); edApellidos = (EditText)findViewById(R.id.edApellidos); edFecha = (EditText)findViewById(R.id.edFecha); edDescripcion = (EditText)findViewById(R.id.edDescrpcion); |
Se define un método llamado nuevaCita(), que se tratará de un evento onClick, dónde se asignará la clase que implementa el driver a una variable de tipo String, además de declarar un array de strings, dónde se almacenan los datos necesarios para establecer la conexión e insertar un nuevo registro, y dónde finalmente se invoca al método execute()
del hilo secundario pasándole como parámetros los datos de conexión y nueva cita a almacenar en la tabla:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public void nuevaCita(View view) { try{ String driver = "com.mysql.jdbc.Driver"; Class.forName(driver).newInstance(); String[] nuevaCita = new String[]{ edNombre.getText().toString(), edApellidos.getText().toString(), edFecha.getText().toString(), edDescripcion.getText().toString(), txtServidor.getText().toString(), txtPuerto.getText().toString(), txtBaseDatos.getText().toString(), txtUsuario.getText().toString(), edPassword.getText().toString() }; [...] new TareaAsincronaInsertar().execute(nuevaCita); [...] } |
SincronizacionBD\app\src\main\java\com\academiaandroid\sincronizacionbd\TareaAsincronaInsertar.java
Clase que hereda de la clase base Asynctask, que permite comunicarse con el hilo principal, y que realizará tareas en segundo plano.
Esta clase define tres tipos genéricos:
1 |
public class TareaAsyncTask extends AsyncTask<params, progress, result> |
Params: tipo de parámetro que se recibirá como entrada para la tarea en el método doInBackground(Params)
Progress: parámetro para actualizar el hilo principal o UIThread
Result: es el resultado devuelto por el procesamiento en segundo plano:
1 |
public class TareaAsincronaInsertar extends AsyncTask<String[],Void,Void> { |
Se declaran dos variable de tipo Connection
y Statement
:
1 2 3 |
private Connection conexionMySQL = null; private Statement st = null; |
Se sobrescribe el método doInBackground
, que será donde se defina el código que se ejecutará en segundo plano. Recibe como parámetro un array de strings declarados en la clase Citas.java, al llamar al método execute(Params). Inicialmente se declaran e inicializan los datos de conexión y nueva cita recibidos desde el hilo principal de la aplicación, accediendo a ellos a través de su posición en el array. Posteriormente, se establece la conexión con el Servidor MySQL indicándole la cadena de conexión formada por la dirección ip, puerto del servidor, la base de datos a la que vamos a conectarnos, y el usuario y contraseña de acceso al servidor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@Override protected void doInBackground(String[]... datos) { String NOMBRE = datos[0][0]; String APELLIDOS = datos[0][1]; String FECHA = datos[0][2]; String DESCRIPCION = datos[0][3]; String SERVIDOR = datos[0][4]; String PUERTO = datos[0][5]; String BD = datos[0][6]; String USUARIO = datos[0][7]; String PASSWORD = datos[0][8]; try{ conexionMySQL = DriverManager.getConnection("jdbc:mysql://" + SERVIDOR + ":" + PUERTO + "/" + BD,USUARIO,PASSWORD); st = conexionMySQL.createStatement(); |
A continuación, se ejecutará la consulta que insertará una nueva cita con los datos introducidos por el usuario:
1 2 3 4 5 6 7 |
st.executeUpdate("INSERT INTO `agenda` (nombre, apellidos, fecha, descripcion) VALUES " + "('" + NOMBRE + "','" + APELLIDOS + "','" + FECHA + "','" + DESCRIPCION + "')"); }catch(SQLException ex) { Log.d("No ha sido posible insertar una nueva cita", ex.getMessage()); } |
Finalmente se cierran las conexiones abiertas con el servidor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
finally { try { st.close(); conexionMySQL.close(); } catch (SQLException e) { e.printStackTrace(); } } return null; } |
SincronizacionBD\app\src\main\res\layout\activity_citas.xml
Se define un layout denominado ‘activity_citas.xml’, que permitirá la inserción de datos en cuatro componentes de tipo EditText (nombre, apellidos, fecha y descripción de la cita), además de un componente de tipo Button para realizar la conexión e insertar la nueva cita:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
<TableLayout android:layout_width="match_parent" android:layout_height="match_parent" > [...] <TableLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#5218ff9c"> <TableRow android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button style="?android:attr/buttonStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/nuevo" android:id="@+id/btnNuevaCita" android:onClick="nuevaCita" > </TableRow> <TableRow android:layout_width="fill_parent" android:layout_height="fill_parent"> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:id="@+id/edNombre" android:inputType="textPersonName" android:hint="@string/nombre" android:layout_weight="1" > [...] </TableRow> </TableLayout> </TableLayout> [...] |
Consultas Transact-SQL
Crear base de datos «citas»:
1 2 |
CREATE DATABASE citas; |
Crear tabla «agenda»:
1 2 3 4 5 6 7 8 9 |
CREATE TABLE `agenda` ( `id` int(11) NOT NULL AUTO_INCREMENT, `nombre` varchar(25) NOT NULL, `apellidos` varchar(25) NOT NULL, `fecha` datetime NOT NULL, `descripcion` varchar(100) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1; |
Estructura tabla «agenda»:
Como se puede apreciar en la imagen, la tabla ‘agenda’, está formada por cinco campos o columnas, dónde además de los campos nombre,apellidos y descripcion (de tipo varchar y no permitiendo valores nulos), se define un campo llamado fecha de tipo DateTime, que almacenará la fecha y hora de una reunión programada.
También se define un campo llamado id, que será la clave primaria de esta tabla, y que se auto incrementa en uno, por cada nuevo registro insertado.
Por último recordar que será necesario declarar dentro del AndroidManifest.xml
los permisos necesarios para la conexión con el servidor remoto, en este caso permisos de Internet:
1 |
<uses-permission android:name="android.permission.INTERNET" /><code> |
Dependencias Gradle implementadas
Será necesario añadir la dependencia para el conector JDBC, cuya librería deberá añadirse dentro de la ruta SincronizacionBD\app\src\lib,en el módulo app:
1 2 3 4 5 |
dependencies { compile 'com.android.support:appcompat-v7:20.0.0' compile 'com.android.support:support-v4:20.0.0' compile files('src/lib/mysql-connector-java-5.1.31-bin.jar') } |
Nota: Uso de la versión 5.1 del servidor de bases de datos MySQL.
Descarga código proyecto
Aquí puedes descargar todo el código de este proyecto
DownloadEsta entrada tiene 9 comentarios
Los comentarios están cerrados.
Estimados, estoy viendo este tutorial y tengo algunas dudas sobre los parámetros para conectarme a la base de datos.
Tengo contratado un servicio de hosting que me permite trabajar con MySQL.
Tengo creada una base de datos a la cual le asignaron permiso para poder conectarme en forma remota.
Los datos que tengo para conectarme a la base de datos son
hostname , nombre base de datos, usuario, contraseña y el número de puerto ( 3306 )
Para el caso de la aplicación Android, ingresé como dato hostname, la dirección IP que me asignaron para conectarme vía FTP.
Nombre de usuario y contraseña: Los mismo que uso para conectarme a mi FTP.
Además en la clase MainActivity cambie la declaración de la base de datos
private String baseDatos = «nombre de mi base de datos»;
Cambie el nombre de la base de datos debido a que tengo ya creada una y es a la que le asignaron los permisos de acceso remoto.
Al ejecutar la aplicación desde mi móvil, no me aparece ningún tipo de error, pero no se conecta.Ingreso los datos y al hace clic en abrir conexión. No sucede nada.
Los datos de MySQL son: Ver 14.14 Distrib 5.6.25, for Linux (x86_64).
La librería ‘mysql-connector-java-5.1.31-bin.jar’es la correcta para esta versión del servidor ?
Que puedo controlar ? o verificar para determinar el error ?
Esperando me puedan ayudar para seguir avanzando en mis conocimientos
Desde ya gracias
Marcelo
Hola Marcelo,
Así de manera rápida, y yendo un poco ‘a ciegas’ al no tener mensajes de error que analizar, nos suena a problemas de conexión (algún parámetro que no es correcto de tu servicio hosting).
Comentar que aunque el proyecto se conecta a una base de datos externa a la aplicación, no se realiza sobre un servidor externo a la máquina donde se ejecuta el emulador de Android, y por lo tanto pueden influir numerosos aspectos, difíciles de conocer por nuestra parte.
De todas maneras, vamos a hacer unas pruebas a ver si podemos detectar algo en el proyecto que fuera la causa o que nos de alguna orientación.
Saludos
Hola, tras revisar el proyecto y probarlo de nuevo, comprobamos que la aplicación funciona bien (y tal como se puede ver en el vídeo) desde el emulador conectándose a un servidor externo MySQL en la red local. Como decíamos, la conexión a servidores fuera de allí implica más elementos y va un poco más allá de este ejemplo, y sin tener tampoco mensajes de error, es difícil decir más.
Una alternativa que no sabemos si has probado, porque nos preguntaste por esos tutoriales sobre arquitectura REST, es utilizar servicios web.
Sentimos no poder decirte más, pero aunque tratamos de ayudaros a los usuarios Premium si tenéis dudas con nuestros contenidos y los conceptos que allí se explican, a veces las consultas requieren más un soporte técnico que investigue problemas teniendo en cuenta configuraciones/entornos particulares. Quizás foros especializados, donde precisamente no se explican las bases/fundamentos pero sí dan este tipo de soporte para problemas concretos, tipo stackoverflow.com, puedan serte una opción.
Un saludo
Hola, gracias por las respuesta.. En realidad aun no probe los servicios REST.. los estoy leyendo. pero no los pruebo aun.
Respecto a la respuesta que me envian Uds, veo que me comentan que estan probando desde el emulador, en mi caso estoy probando con mi dispositivo movil real.. Eso puede influir ??
De todos modos seguire con el tema REST .
Saludos y muchas gracias…
Hola, muchas gracias por compartir tu conocimiento con nosotros, no ve el codigo, me podrías ayudar, gracias.
Hola Mario, disculpa pero no entendemos bien tu comentario. Si te refieres a ver el código, puedes hacerlo dándote de alta como usuario Premium (las suscripciones y accesos premium nos permiten pagar a nuestros autores y seguir publicando, una buena parte en abierto, y sin ninguna publicidad).
Gracias
He empezado a Testear este ejemplo.
Aunque se un ejemplo hay muchos errores sin controlar:
– Si pongo datos erróneos de conexión a la Base da Datos, no sale ningún error…
– El campo de Fecha es un campo de texto en vez de un campo tipo fecha.
– Si se introduce una fecha mal, la acepta y pone «Nuevo Registro Insertado» y si se verifica la Base de Datos no llega introducir el datos. (La fecha queda Truncada)
– Si se detiene los servicios mysql (Simulando un corte en el servidor) … la aplicación sigue poniendo «Nuevo Registro Insertado» …
– Si se pone un carácter (símbolo especial / reservado) se produce un error «Error SQL syntax» .. (Inyección SQL, por falta de control de entrada de los caracteres.)
– No he revisado el código aun..
¿Pueden revisar el ejemplo y aplicar las correcciones?
Gracias.
Corrijo:
– Si se pone un carácter (símbolo especial / reservado) se produce un error “Error SQL syntax” (En la consola de android studio) .. (Inyección SQL, por falta de control de entrada de los caracteres.)
Pero pone igualmente que se ha insertado el registro …
Hola Daniel,
lo primero agradecerte el testeo que estás haciendo y comentárnoslo.
Como dices, esto es un ejemplo simplificado para mostrar unas funcionalidades concretas (como sucede en casi todos los proyectos publicados) y no pretende ser una aplicación final, donde el control de errores y de todo tipo de situaciones que puedan darse, es muy importante.
Igual podríamos decir en general de otros aspectos de estos proyectos ejemplo, como el diseño de la interfaz de usuario, que suele ser muy ‘esquemático’ y que se plantearía de una forma más elaborada si estuviera destinado a una aplicación que va ser distribuida y utilizada en real.
Dicho ésto, intentaremos revisar lo que nos dices y si se genera una nueva versión del proyecto lo publicaríamos aquí mismo.
Gracias de nuevo por tu interés. Un saludo.