Spanish (Español) translation by Ana Paulina Figueroa Vazquez (you can also view the original English article)

Con Firebase, crear aplicaciones de redes sociales en tiempo real es un trabajo sencillo. Y lo mejor de todo: no tienes que escribir una sola línea de código del lado del servidor.
En este tutorial te enseñaré cómo aprovechar Firebase UI para crear una aplicación de grupo de chat que puedes compartir con tus amigos. Se trata de una aplicación muy sencilla con una sola sala de chat que estará abierta para todos los usuarios.
Como habrás adivinado, la aplicación dependerá de Firebase Auth para administrar el registro e inicio de sesión de los usuarios. También usará la base de datos de Firebase en tiempo real para almacenar los mensajes del grupo de chat.
Requisitos previos
Para poder seguir este tutorial paso a paso necesitarás lo siguiente:
- La versión más reciente de Android Studio
- Una cuenta de Firebase
Para obtener instrucciones sobre cómo crear una cuenta de Firebase y prepararte para el desarrollo con Firebase en Android Studio, consulta mi tutorial Cómo comenzar con Firebase para Android aquí en Envato Tuts+.
1. Crea un proyecto en Android Studio
Ejecuta Android Studio y crea una nuevo proyecto con una actividad vacía llamada MainActivity.

Para configurar el proyecto para que use la plataforma Firebase, abre la ventana del Asistente de Firebase haciendo clic en Tools > Firebase (Herramientas > Firebase).
Al usar la plataforma Firebase por lo general es una buena idea añadir Firebase Analytics al proyecto. Por lo tanto, dentro de la ventana del Asistente de Firebase ve a la sección Analytics y presiona la opción Log an Analytics event (Registrar un evento de Analytics).

A continuación presiona el botón Connect to Firebase (Conectar con Firebase) y asegúrate de que la opción Create new Firebase project (Crear nuevo proyecto de Firebase) esté seleccionada. Una vez que la conexión haya sido establecida presiona el botón Add Analytics to your app (Añadir Analytics a tu aplicación).

En este punto el proyecto de Android Studio no solamente está integrado con Firebase Analytics, sino que también está listo para usar el resto de los servicios de Firebase.
2. Añade dependencias
Vamos a usar dos bibliotecas en este proyecto: Firebase UI y la biblioteca de soporte para diseño de Android. Por lo tanto, abre el archivo build.gradle del módulo app
y agrega las siguientes dependencias compile
:
compile 'com.android.support:design:23.4.0' compile 'com.firebaseui:firebase-ui:0.6.0'
Presiona el botón Sync Now (Sincronizar ahora) para actualizar el proyecto.
3. Define diseños
El archivo activity_main.xml, que ya está vinculado con MainActivity
, define los contenidos de la pantalla de inicio de la aplicación. En otras palabras, representará a la sala de chat.
Al igual que la mayoría del resto de las aplicaciones de grupos de chat disponibles hoy en día, nuestra aplicación tendrá los siguientes elementos en la interfaz de usuario:
- Una lista que muestre todos los mensajes del grupo de chat en orden cronológico
- Un campo de entrada en el que el usuario pueda escribir un mensaje nuevo
- Un botón que el usuario pueda presionar para publicar el mensaje
Por lo tanto, activity_main.xml debe tener un ListView
, un EditText
y un FloatingActionButton
. Después de colocarlos dentro de un widget RelativeLayout
, tu diseño en XML deberá verse así:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.tutsplus.mychatapp.MainActivity"> <android.support.design.widget.FloatingActionButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="true" android:src="@drawable/ic_send_black_24dp" android:id="@+id/fab" android:tint="@android:color/white" android:layout_alignParentBottom="true" android:layout_alignParentEnd="true" app:fabSize="mini" /> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_toLeftOf="@id/fab" android:layout_alignParentBottom="true" android:layout_alignParentStart="true"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Input" android:id="@+id/input" /> </android.support.design.widget.TextInputLayout> <ListView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentTop="true" android:layout_alignParentStart="true" android:layout_above="@id/fab" android:dividerHeight="16dp" android:divider="@android:color/transparent" android:id="@+id/list_of_messages" android:layout_marginBottom="16dp"/> </RelativeLayout>
Toma en cuenta que he colocado el widget EditText
dentro de un widget TextInputLayout
. Al hacer esto se agrega una etiqueta flotante al EditText
, que es importante si quieres cumplir con las pautas del Material Design.
Ahora que el diseño de la pantalla de inicio está listo podemos continuar creando un diseño para los mensajes del chat, que son elementos contenidos en un ListView
. Comienza creando un nuevo archivo de diseño XML llamado message.xml, cuyo elemento raíz sea RelativeLayout
.
El diseño debe tener widgets TextView
para mostrar el texto del mensaje del chat, la hora a la que fue enviado y su autor. Siéntete en la libertad de colocarlos en cualquier orden. Este es el diseño que usaré:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentStart="true" android:id="@+id/message_user" android:textStyle="normal|bold" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/message_user" android:layout_alignParentEnd="true" android:id="@+id/message_time" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/message_user" android:layout_alignParentStart="true" android:layout_marginTop="5dp" android:id="@+id/message_text" android:textAppearance="@style/TextAppearance.AppCompat.Body1" android:textSize="18sp" /> </RelativeLayout>
4. Gestiona la autenticación del usuario
Permitir que los usuarios publiquen mensajes de forma anónima en la sala de chat sería una muy mala idea. Esto podría ocasionar spam, problemas de seguridad y una experiencia de chat poco deseable para los usuarios. Por lo tanto, vamos a configurar nuestra aplicación para que solamente los usuarios registrados puedan leer y publicar mensajes.
Comienza yendo a la sección Auth (Autorización) de la Consola de Firebase y habilitando Email/Password (Correo/Contraseña) como proveedor de inicio de sesión.

Siéntete en la libertad de habilitar proveedores de inicio de sesión OAuth 2.0 también. Sin embargo, FirebaseUI v0.6.0 solamente es compatible sin problemas con el inicio de sesión de Google y Facebook.
Paso 1: Gestiona el inicio de sesión del usuario
Tan pronto como la aplicación arranque, ésta debe verificar si el usuario ha iniciado sesión. Si es así, la aplicación debe continuar y mostrar el contenido de la sala de chat. De lo contrario, ésta debe redirigir al usuario ya sea a una pantalla de inicio de sesión o a una de registro. Con FirebaseUI, la creación de esas pantallas requiere mucho menos código del que podrías imaginar.
Dentro del método onCreate()
de MainActivity
, revisa si el usuario ya inició sesión verificando si el objeto FirebaseUser
actual no es null
. Si es null
, debes crear y configurar un objeto Intent
que abre una activity de inicio de sesión. Para hacer esto usa la clase SignInIntentBuilder
. Una vez que el intent esté listo, debes ejecutar la activity de inicio de sesión usando el método startActivityForResult()
.
Toma en cuenta que la activity de inicio de sesión también permite el registro de nuevos usuarios. Por lo tanto no es necesario que escribas código adicional para gestionar el registro de usuarios.
Agrega el siguiente código al método onCreate()
:
if(FirebaseAuth.getInstance().getCurrentUser() == null) { // Start sign in/sign up activity startActivityForResult( AuthUI.getInstance() .createSignInIntentBuilder() .build(), SIGN_IN_REQUEST_CODE ); } else { // User is already signed in. Therefore, display // a welcome Toast Toast.makeText(this, "Welcome " + FirebaseAuth.getInstance() .getCurrentUser() .getDisplayName(), Toast.LENGTH_LONG) .show(); // Load chat room contents displayChatMessages(); }
Como puedes ver en el código anterior, si el usuario ya inició sesión primero mostramos un Toast
que saludará al usuario, y posteriormente invocamos al método llamado displayChatMessages. Por ahora solamente crea el esqueleto del método. Vamos a añadirle código posteriomente.
private void displayChatMessages() { }
Una vez que el usuario haya iniciado sesión, MainActivity
recibirá un resultado en forma de un Intent
. Para manejarlo, debes sobrescribir el método onActivityResult()
.
Si el código del resultado es RESULT_OK
, esto significa que el usuario ha iniciado sesión con éxito. De ser así, debes invocar al método displayChatMessages()
de nuevo. De lo contrario invoca finish()
para cerrar la aplicación.
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode == SIGN_IN_REQUEST_CODE) { if(resultCode == RESULT_OK) { Toast.makeText(this, "Successfully signed in. Welcome!", Toast.LENGTH_LONG) .show(); displayChatMessages(); } else { Toast.makeText(this, "We couldn't sign you in. Please try again later.", Toast.LENGTH_LONG) .show(); // Close the app finish(); } } }
En este punto puedes ejecutar la aplicación y revisar las pantallas de registro y de inicio de sesión.

Paso 2: Gestiona el cierre de sesión del usuario
De forma predeterminada FirebaseUI usa el Bloqueo Inteligente para Contraseñas. Por lo tanto, una vez que los usuarios inicien sesión éstos permanecerán en ella incluso si reinician la aplicación. Para permitir que los usuarios cierren sesión agregaremos la opción correspondiente al menú de desbordamiento de MainActivity
.
Crea un nuevo archivo de recursos de menú llamado main_menu.xml y agrégale un elemento item
único cuyo atributo title
tenga el valor Sign out (Cerrar sesión). El contenido del archivo debe verse así:
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:title="Sign out" app:showAsAction="never" android:id="@+id/menu_sign_out"/> </menu>
Para instanciar el recurso de menú dentro de MainActivity
, sobrescribe el método onCreateOptionsMenu()
e invoca al método inflate()
del objeto MenuInflater
.
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main_menu, menu); return true; }
A continuación, sobrescribe el método onOptionsItemSelected()
para gestionar los eventos clic en el elemento del menú. Dentro del método puedes invocar a la función signOut()
de la clase AuthUI
para cerrar la sesión del usuario. Dado que la operación de cierre de sesión se ejecuta de forma asíncrona, también vamos a añadirle un OnCompleteListener
.
@Override public boolean onOptionsItemSelected(MenuItem item) { if(item.getItemId() == R.id.menu_sign_out) { AuthUI.getInstance().signOut(this) .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { Toast.makeText(MainActivity.this, "You have been signed out.", Toast.LENGTH_LONG) .show(); // Close activity finish(); } }); } return true; }
Una vez que el usuario haya cerrado su sesión, la aplicación deberá cerrarse automáticamente. Esa es la razón por la que ves una llamada al método finish()
en el código anterior.
5. Crea un modelo
Para almacenar los mensajes de chat en la base de datos de Firebase en tiempo real, debes crear un modelo para ellos. El diseño del mensaje de chat, que creamos anteriormente en este tutorial, tiene tres vistas. Para poder llenar esas vistas, el modelo también debe tener al menos tres campos.
Crea una nueva clase de Java llamada ChatMessage.java y agrégale tres variables miembro: messageText
, messageUser
y messageTime
. Además agrega un constructor para inicializar esas variables.
Para que el modelo sea compatible con FirebaseUI, también debes añadirle un constructor predeterminado junto con funciones get y set para todas las variables miembro.
En este punto, la clase ChatMessage
debe verse así:
public class ChatMessage { private String messageText; private String messageUser; private long messageTime; public ChatMessage(String messageText, String messageUser) { this.messageText = messageText; this.messageUser = messageUser; // Initialize to current time messageTime = new Date().getTime(); } public ChatMessage(){ } public String getMessageText() { return messageText; } public void setMessageText(String messageText) { this.messageText = messageText; } public String getMessageUser() { return messageUser; } public void setMessageUser(String messageUser) { this.messageUser = messageUser; } public long getMessageTime() { return messageTime; } public void setMessageTime(long messageTime) { this.messageTime = messageTime; } }
6. Publica un mensaje de chat
Ahora que el modelo está listo, podemos añadir fácilmente nuevos mensajes de chat a la base de datos de Firebase en tiempo real.
Para publicar un mensaje nuevo el usuario presionará el FloatingActionButton
. Por lo tanto debes añadirle un OnClickListener
.
Dentro del listener, primero debes obtener un objeto DatabaseReference
usando el método getReference()
de la clase FirebaseDatabase
. Después puedes hacer llamadas a los métodos push()
y setValue()
para añadir nuevas instancias de la clase ChatMessage
a la base de datos en tiempo real.
Desde luego, las instancias ChatMessage
deben ser inicializadas usando los contenidos del EditText
y el nombre para mostrar del usuario registrado actualmente.
En consecuencia, agrega el siguiente código al método onCreate()
:
FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { EditText input = (EditText)findViewById(R.id.input); // Read the input field and push a new instance // of ChatMessage to the Firebase database FirebaseDatabase.getInstance() .getReference() .push() .setValue(new ChatMessage(input.getText().toString(), FirebaseAuth.getInstance() .getCurrentUser() .getDisplayName()) ); // Clear the input input.setText(""); } });
Los datos de la base de datos de Firebase en tiempo real siempre se almacenan como pares clave-valor. Sin embargo, si observas el código anterior podrás ver que estamos invocando a setValue()
sin especificar una clave. Esto se permite solamente debido a que la llamada al método setValue()
está precedida por una llamada al método push()
, quien genera una nueva clave automáticamente.
7. Muestra los mensajes de chat
FirebaseUI tiene una clase muy útil llamada FirebaseListAdapter, que reduce dramáticamente el esfuerzo requerido para llenar un ListView
usando datos que se encuentran presentes en la base de datos de Firebase en tiempo real. Vamos a usarla ahora para recuperar y mostrar todos los objetos ChatMessage
que estén presentes en la base de datos.
Añade un objeto FirebaseListAdapter
como una nueva variable miembro de la clase MainActivity
.
private FirebaseListAdapter<ChatMessage> adapter;
Dentro del método displayChatMessages()
inicializa el adaptador usando su constructor, el cuál espera los siguientes argumentos:
- Una referencia a la
Activity
- La
class
(clase) del objeto en el que estés interesado
- El diseño de los elementos de la lista
- Un objeto
DatabaseReference
FirebaseListAdapter
es una clase abstracta y tiene un método populateView()
abstracto que debe sobrescribirse.
Como su nombre sugiere, populateView()
se usa para llenar las vistas de cada elemento de la lista. Si estás familiarizado con la clase ArrayAdapter
, puedes pensar en populateView()
como una alternativa al método getView()
.
Dentro del método, primero debes usar findViewById()
para obtener referencias a cada TextView
que esté presente en el archivo de diseño message.xml. Después puedes invocar a sus métodos setText()
y llenarlos usando las funciones get de la clase ChatMessage
.
En este punto, el contenido del método displayChatMessages()
debe verse así:
ListView listOfMessages = (ListView)findViewById(R.id.list_of_messages); adapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class, R.layout.message, FirebaseDatabase.getInstance().getReference()) { @Override protected void populateView(View v, ChatMessage model, int position) { // Get references to the views of message.xml TextView messageText = (TextView)v.findViewById(R.id.message_text); TextView messageUser = (TextView)v.findViewById(R.id.message_user); TextView messageTime = (TextView)v.findViewById(R.id.message_time); // Set their text messageText.setText(model.getMessageText()); messageUser.setText(model.getMessageUser()); // Format the date before showing it messageTime.setText(DateFormat.format("dd-MM-yyyy (HH:mm:ss)", model.getMessageTime())); } }; listOfMessages.setAdapter(adapter);
La aplicación de grupo de chat está lista. Ejecútala y publica nuevos mensajes para verlos aparecer inmediatamente en el ListView
. Si compartes la aplicación con tus amigos podrás ver sus mensajes también tan pronto como los publiquen.
Conclusión
En este tutorial aprendiste cómo usar Firebase y FirebaseUI para crear una aplicación de grupo de chat muy sencilla. También viste lo fácil que es trabajar con las clases disponibles en FirebaseUI para crear nuevas pantallas rápidamente e implementar funcionalidad compleja.
Para aprender más sobre Firebase y FirebaseUI revisa la documentación oficial. ¡O también puedes revisar algunos de nuestros otros tutoriales de Firebase aquí en Envato Tuts+!
- Android SDKCómo comenzar con Firebase para AndroidAshraff Hathibelagal
- Android SDKAndroid desde cero: Reporte de errores en FirebaseAshraff Hathibelagal
- JavaScriptUsa Firebase como Back-EndReginald Dawson
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post