Firebase Android Codelab
1. Visión de conjunto

Image: Working Friendly Chat app.
Bienvenido al codelab de Friendly Chat. En este conjunto de códigos, aprenderá a usar la plataforma de Firebase para crear aplicaciones de Android. Implementarás un cliente de chat y supervisarás su rendimiento usando Firebase.
Lo que aprendes a hacer
- Permitir a los usuarios iniciar sesión
- Sincronice los datos usando Firebase Realtime Database.
- Recibe mensajes en segundo plano con Firebase Notifications.
- Configure una aplicación con Firebase Remote Config.
- Rastree los flujos de uso de aplicaciones con Google Analytics para Firebase.
- Permitir a los usuarios enviar invitaciones para instalar con Firebase Invites.
- Mostrar anuncios con AdMob.
- Informes bloqueados con Firebase Crash Reporting.
- Pon a prueba tu aplicación con Firebase Test Lab.
2. Obtenga el código de muestra
Clona el repositorio de GitHub desde la línea de comando:$ git clone https://github.com/firebase/friendlychat-android
3. Importar la aplicación de inicio
Desde Android Studio, seleccione laandroid-start
directorio (
Ahora debería tener abierto el proyecto android-start en Android Studio.
4. Crear proyecto de consola de Firebase
- Go to the Firebase console.
- Select Create New Project, and name your project "FriendlyChat."
Conecte su aplicación de Android
- Desde la pantalla de resumen de su nuevo proyecto,
click Add Firebase to your Android app. - Ingrese el nombre del paquete del codelab:
com.google.firebase.codelab.friendlychat
. - Introducir el SHA1 de su almacén de claves de firma. Si está utilizando el almacén de claves de depuración estándar, use el comando a continuación para encontrar el SHA1 picadillo:
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v -storepass android
Agregue el archivo google-services.json a su aplicación
Después de agregar el nombre del paquete y SHA1 y seleccionar Continuar, su navegador descarga automáticamente un archivo de configuración que contiene todos los metadatos de Firebase necesarios para su aplicación. Copie el archivo google-services.json en el directorio de la aplicación en su proyecto.Agrega el complemento google-services a tu aplicación
El complemento google-services usa el archivo google-services.json para configurar su aplicación para usar Firebase. La siguiente línea ya debe estar agregada al final del archivo build.gradle en el directorio de la aplicación de su proyecto (verifique para confirmar):apply plugin: 'com.google.gms.google-services'
Sincronice su proyecto con archivos gradle
Para asegurarse de que todas las dependencias estén disponibles para su aplicación, debe sincronizar su proyecto con archivos gradle en este momento. Seleccionar Sync Project with Gradle Files (
5. Ejecuta la aplicación de inicio
Ahora que ha importado el proyecto a Android Studio y configurado el complemento google-services con su archivo JSON, está listo para ejecutar la aplicación por primera vez. Conecte su dispositivo Android y haga clic Run (
La aplicación debe iniciarse en su dispositivo. En este punto, debería ver una lista de mensajes vacía, y enviar y recibir mensajes no funcionará. En la siguiente sección, autenticas a los usuarios para que puedan usar Friendly Chat.
6. Habilitar autenticación
Solicitemos que el usuario inicie sesión antes de leer o publicar cualquier mensaje de conversación amistosa.Reglas de la base de datos de Firebase Realtime
Acceso a tu Firebase Database está configurado por un conjunto de reglas escritas en un lenguaje de configuración JSON.Vaya a su proyecto en la consola de Firebase y seleccione Database. Seleccionar Get Started in the Realtime Database opción. Cuando se le soliciten las reglas de seguridad, elija comenzar en cualquiera test mode or locked mode, escoger test mode. Una vez que se establecen las reglas predeterminadas, seleccione la pestaña Reglas y actualice la configuración de las reglas con lo siguiente:
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
Para obtener más información sobre cómo funciona esto (incluida la documentación sobre la variable "auth"), consulte la Firebase security documentation.Configurar las API de autenticación
Antes de que su aplicación pueda acceder al Firebase Authentication APIs en nombre de sus usuarios, tendrá que habilitarlo- Navigate to the Firebase console and select your project
- Select Authentication
- Select the Sign In Method tab
- Palanca the Google switch to enabled (blue)
- Press Save on the resulting dialog
Añadir dependencia Firebase Auth
El SDK firebase-auth permite una fácil administración de usuarios autenticados de su aplicación. Confirma la existencia de esta dependencia en tuapp/build.gradle
archivo.app/build.gradle
implementation 'com.google.firebase:firebase-auth:15.0.0'
Agregue las variables de instancia de Auth en MainActivity
class:MainActivity.java (instance variable)
// Firebase instance variables
private FirebaseAuth mFirebaseAuth;
private FirebaseUser mFirebaseUser;
Verificar el usuario actual
Ahora modifiquemosMainActivity.java
para enviar al usuario a la pantalla de inicio de sesión cada vez que abre la aplicación y no está autenticado. Agregue lo siguiente a
onCreate
método después mUsername
ha sido inicializado:MainActivity.java
// Initialize Firebase Auth
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseUser = mFirebaseAuth.getCurrentUser();
if (mFirebaseUser == null) {
// Not signed in, launch the Sign In activity
startActivity(new Intent(this, SignInActivity.class));
finish();
return;
} else {
mUsername = mFirebaseUser.getDisplayName();
if (mFirebaseUser.getPhotoUrl() != null) {
mPhotoUrl = mFirebaseUser.getPhotoUrl().toString();
}
}
A continuación, agregue una nueva caja a onOptionsItemSelected () para manejar el botón de cerrar sesión:MainActivity.java
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.sign_out_menu:
mFirebaseAuth.signOut();
Auth.GoogleSignInApi.signOut(mGoogleApiClient);
mUsername = ANONYMOUS;
startActivity(new Intent(this, SignInActivity.class));
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Ahora tenemos toda la lógica en el lugar para enviar al usuario a la
pantalla de inicio de sesión cuando sea necesario. A continuación,
debemos implementar la pantalla de inicio de sesión para autenticar
correctamente a los usuarios.Implementar la pantalla de inicio de sesión
Abra el archivo SignInActivity.java. Aquí se usa un botón de inicio de sesión simple para iniciar la autenticación. En este paso, implementará la lógica para Sign-In con Google, y luego usar esa cuenta de Google para autenticarse con Firebase.Agregue una variable de instancia Auth en
SignInActivity
class:SignInActivity.java
// Firebase instance variables
private FirebaseAuth mFirebaseAuth;
Luego, edita el onCreate()
método para inicializar Firebase de la misma manera que lo hizo en MainActivity
:SignInActivity.java
// Initialize FirebaseAuth
mFirebaseAuth = FirebaseAuth.getInstance();
A continuación, inicie sesión con Google. Actualizar SignInActivity
's onClick
método para que se vea así:SignInActivity.java
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.sign_in_button:
signIn();
break;
}
}
Agregue el método de inicio de sesión requerido que realmente presenta al usuario con el Google Sign-In UI.SignInActivity.java
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
A continuación, agregue el método onActivityResult a SignInActivity
para gestionar el resultado de inicio de sesión. Si el resultado de la Google Sign-In was successful, uSe la cuenta para autenticarse con Firebase.SignInActivity.java
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
// Google Sign-In was successful, authenticate with Firebase
GoogleSignInAccount account = result.getSignInAccount();
firebaseAuthWithGoogle(account);
} else {
// Google Sign-In failed
Log.e(TAG, "Google Sign-In failed.");
}
}
}
Agregue el requerido firebaseAuthWithGoogle
método para autenticarse con la cuenta de Google iniciada:SignInActivity.java
private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
Log.d(TAG, "firebaseAuthWithGooogle:" + acct.getId());
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
mFirebaseAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w(TAG, "signInWithCredential", task.getException());
Toast.makeText(SignInActivity.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
} else {
startActivity(new Intent(SignInActivity.this, MainActivity.class));
finish();
}
}
});
}
¡Eso es! Ha implementado la autenticación utilizando Google como
proveedor de identidad en solo unas pocas llamadas a métodos y sin
necesidad de administrar ninguna configuración del lado del servidor.Pon a prueba tu trabajo
Ejecuta la aplicación en tu dispositivo. Debería ser enviado inmediatamente a la pantalla de inicio de sesión. Toca el botón de inicio de sesión de Google. Luego, debe enviarlo a la pantalla de mensajes si todo funcionó bien.7. Leer mensajes
Importar mensajes
- En su proyecto en la consola de Firebase, seleccione Database en el menú de navegación izquierdo.
- En el menú de desbordamiento de la base de datos, seleccione Import JSON.
- Busque el archivo initial_messages.json en la raíz del repositorio clonado y selecciónelo.
- Click Import.
root
messages
-K2ib4H77rj0LYewF7dP
text: "hello"
name: "anonymous"
-K2ib5JHRbbL0NrztUfO
text: "how are you"
name: "anonymous"
-K2ib62mjHh34CAUbide
text: "i am fine"
name: "anonymous"
Añadir Firebase Realtime Database and Firebase Storage dependencias
En el bloque de dependencias del archivo app / build.gradle, se deben incluir las siguientes dependencias. Para este codelab, ya se agregaron por conveniencia; confirme esto mirando en el archivo app / build.gradle:Dependency in app/build.gradle
implementation 'com.google.firebase:firebase-database:15.0.0'
implementation 'com.google.firebase:firebase-storage:15.0.0'
Sincronizar mensajes
En esta sección agregamos un código que sincroniza los mensajes recién agregados a la interfaz de usuario de la aplicación al:- Initializing the Firebase Realtime Database and adding a listener to handle changes made to the data.
- Updating the
RecyclerView
adapter so new messages will be shown. - Adding the Database instance variables in the
MainActivity
class:
MainActivity.java
// Firebase instance variables
private DatabaseReference mFirebaseDatabaseReference;
private FirebaseRecyclerAdapter<FriendlyMessage, MessageViewHolder>
mFirebaseAdapter;
Modify your MainActivity's onCreate
method by replacing mProgressBar.setVisibility(ProgressBar.INVISIBLE);
with
the code defined below. This code initially adds all existing messages
and then listens for new child entries under the messages path in your
Firebase Realtime Database. It adds a new element to the UI for each
message:MainActivity.java
// New child entries
mFirebaseDatabaseReference = FirebaseDatabase.getInstance().getReference();
SnapshotParser<FriendlyMessage> parser = new SnapshotParser<FriendlyMessage>() {
@Override
public FriendlyMessage parseSnapshot(DataSnapshot dataSnapshot) {
FriendlyMessage friendlyMessage = dataSnapshot.getValue(FriendlyMessage.class);
if (friendlyMessage != null) {
friendlyMessage.setId(dataSnapshot.getKey());
}
return friendlyMessage;
}
};
DatabaseReference messagesRef = mFirebaseDatabaseReference.child(MESSAGES_CHILD);
FirebaseRecyclerOptions<FriendlyMessage> options =
new FirebaseRecyclerOptions.Builder<FriendlyMessage>()
.setQuery(messagesRef, parser)
.build();
mFirebaseAdapter = new FirebaseRecyclerAdapter<FriendlyMessage, MessageViewHolder>(options) {
@Override
public MessageViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
return new MessageViewHolder(inflater.inflate(R.layout.item_message, viewGroup, false));
}
@Override
protected void onBindViewHolder(final MessageViewHolder viewHolder,
int position,
FriendlyMessage friendlyMessage) {
mProgressBar.setVisibility(ProgressBar.INVISIBLE);
if (friendlyMessage.getText() != null) {
viewHolder.messageTextView.setText(friendlyMessage.getText());
viewHolder.messageTextView.setVisibility(TextView.VISIBLE);
viewHolder.messageImageView.setVisibility(ImageView.GONE);
} else if (friendlyMessage.getImageUrl() != null) {
String imageUrl = friendlyMessage.getImageUrl();
if (imageUrl.startsWith("gs://")) {
StorageReference storageReference = FirebaseStorage.getInstance()
.getReferenceFromUrl(imageUrl);
storageReference.getDownloadUrl().addOnCompleteListener(
new OnCompleteListener<Uri>() {
@Override
public void onComplete(@NonNull Task<Uri> task) {
if (task.isSuccessful()) {
String downloadUrl = task.getResult().toString();
Glide.with(viewHolder.messageImageView.getContext())
.load(downloadUrl)
.into(viewHolder.messageImageView);
} else {
Log.w(TAG, "Getting download url was not successful.",
task.getException());
}
}
});
} else {
Glide.with(viewHolder.messageImageView.getContext())
.load(friendlyMessage.getImageUrl())
.into(viewHolder.messageImageView);
}
viewHolder.messageImageView.setVisibility(ImageView.VISIBLE);
viewHolder.messageTextView.setVisibility(TextView.GONE);
}
viewHolder.messengerTextView.setText(friendlyMessage.getName());
if (friendlyMessage.getPhotoUrl() == null) {
viewHolder.messengerImageView.setImageDrawable(ContextCompat.getDrawable(MainActivity.this,
R.drawable.ic_account_circle_black_36dp));
} else {
Glide.with(MainActivity.this)
.load(friendlyMessage.getPhotoUrl())
.into(viewHolder.messengerImageView);
}
}
};
mFirebaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
int friendlyMessageCount = mFirebaseAdapter.getItemCount();
int lastVisiblePosition =
mLinearLayoutManager.findLastCompletelyVisibleItemPosition();
// If the recycler view is initially being loaded or the
// user is at the bottom of the list, scroll to the bottom
// of the list to show the newly added message.
if (lastVisiblePosition == -1 ||
(positionStart >= (friendlyMessageCount - 1) &&
lastVisiblePosition == (positionStart - 1))) {
mMessageRecyclerView.scrollToPosition(positionStart);
}
}
});
mMessageRecyclerView.setAdapter(mFirebaseAdapter);
Appropriately start and stop listening for updates from Firebase Realtime Database. Update the onPause
and onResume
methods in MainActivity
as shown below.MainActivity.java
@Override
public void onPause() {
mFirebaseAdapter.stopListening();
super.onPause();
}
@Override
public void onResume() {
super.onResume();
mFirebaseAdapter.startListening();
}
Test message sync
- Click Run (
).
- Add new messages directly in the Database section of the Firebase console. Confirm that they show up in the Friendly-Chat UI.
- Navigate to the Database section of the Firebase console. From the Data tab, select the '+' sign on the messages element.
- Give the new element a name of -ABCD (note the '-' sign) and leave the value empty for now.
- Select the '+' sign on the -ABCD element
- Give the new element a name of "name" and value of "Mary"
- Select the '+' sign on the -ABCD element again
- Give the new element a name of "text" and value of "hello"
- Select Add
8. Send Messages
Implement text message sending
In this section, you will add the ability for app users to send text messages. The code snippet below listens for click events on the send button, creates a newFriendlyMessage
object with the contents of the message field, and pushes the message to the database. The push()
method adds an automatically generated ID to the pushed object's path.
These IDs are sequential which ensures that the new messages will be
added to the end of the list. Update the
onClick
method of mSendButton
in the onCreate
method in the MainActivity
class. This code is at the bottom of the onCreate
method already. Update the onClick
body to match the code below:MainActivity.java
mSendButton = (Button) findViewById(R.id.sendButton);
mSendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
FriendlyMessage friendlyMessage = new
FriendlyMessage(mMessageEditText.getText().toString(),
mUsername,
mPhotoUrl,
null /* no image */);
mFirebaseDatabaseReference.child(MESSAGES_CHILD)
.push().setValue(friendlyMessage);
mMessageEditText.setText("");
}
});
Implement image message sending
In this section, you will add the ability for app users to send image messages. Creating an image message is done with these steps:- Select image
- Handle image selection
- Write temporary image message to the RTDB
- Begin to upload selected image
- Update image message URL to that of the uploaded image, once upload is complete
Select Image
With the following code snippet you will allow the user to select an image from the device's local storage. Update theonClick
method of mAddMessageImageView
in the onCreate
method in the MainActivity
class. This code is at the bottom of the onCreate
method already. Update the onClick
body to match the code below:MainActivity.java
mAddMessageImageView = (ImageView) findViewById(R.id.addMessageImageView);
mAddMessageImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, REQUEST_IMAGE);
}
});
Handle image selection and write temp message
Once the user has selected an image, a call to theMainActivity
's onActivityResult
will be fired. This is where you handle the user's image selection. Using the code snippet below, add the onActivityResult
method to MainActivity
. In this function you will write a message with a temporary image url to the database indicating the image is being uploaded.MainActivity.java
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult: requestCode=" + requestCode + ", resultCode=" + resultCode);
if (requestCode == REQUEST_IMAGE) {
if (resultCode == RESULT_OK) {
if (data != null) {
final Uri uri = data.getData();
Log.d(TAG, "Uri: " + uri.toString());
FriendlyMessage tempMessage = new FriendlyMessage(null, mUsername, mPhotoUrl,
LOADING_IMAGE_URL);
mFirebaseDatabaseReference.child(MESSAGES_CHILD).push()
.setValue(tempMessage, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError,
DatabaseReference databaseReference) {
if (databaseError == null) {
String key = databaseReference.getKey();
StorageReference storageReference =
FirebaseStorage.getInstance()
.getReference(mFirebaseUser.getUid())
.child(key)
.child(uri.getLastPathSegment());
putImageInStorage(storageReference, uri, key);
} else {
Log.w(TAG, "Unable to write message to database.",
databaseError.toException());
}
}
});
}
}
}
}
Upload image and update message
Add the methodputImageInStorage
to MainActivity
. It is called in onActivityResult
to initiate the upload of the selected image. Once the upload is
complete you will update the message to use the appropriate image. MainActivity.java
private void putImageInStorage(StorageReference storageReference, Uri uri, final String key) {
storageReference.putFile(uri).addOnCompleteListener(MainActivity.this,
new OnCompleteListener<UploadTask.TaskSnapshot>() {
@Override
public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
if (task.isSuccessful()) {
FriendlyMessage friendlyMessage =
new FriendlyMessage(null, mUsername, mPhotoUrl,
task.getResult().getMetadata().getDownloadUrl()
.toString());
mFirebaseDatabaseReference.child(MESSAGES_CHILD).child(key)
.setValue(friendlyMessage);
} else {
Log.w(TAG, "Image upload task was not successful.",
task.getException());
}
}
});
}
Test Sending Messages
- Click the
Run button.
- Enter a message and hit the send button, the new message should be visible in the app UI and in the Firebase console.
- Tap the "+" image to select an image from your device. The new message should be visible first with a placeholder image, and then with the selected image once the image upload is complete. The new message should also be visible in the Firebase console, as an object in the Database and as a blob in Storage.