Materia de Aplicaciones Móviles y Servicios Telemáticos
Demostrar el acceso a los recursos en red para la programación de aplicaciones móviles avanzadas.
Recursos: Android Studio, Google Cloud, FireBase.
Duración: 7 horas
Instrucciones
Actividades
Asegúrese de que su Minimum API level sea API 16 (Jelly Bean) o mayor.
Para este curso, el lenguaje a utilizar será JAVA.
No marcar “Use legacy android.support libraries”.
En caso de que ya existan proyectos en el repositorio de Firebase, hacer clic en el siguiente botón de Agregar app:
android {
namespace 'com.example.appamst_laba_firebase'
compileSdk 33
defaultConfig {
applicationId "com.example.appamst_laba_firebase"
minSdk 16
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
Apodo: Es un identificador interno y conveniente que solo tú puedes ver en Firebase console.
Certificado de firma SHA‑1 de depuración: Firebase Authentication.
Importante: Para la autenticación, requiere agregar el certificado de firma SHA‑1 de depuración.
Archivo: build.gradle (Project:amstfirebaseapp)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
// Make sure that you have the following two repositories
google() // Google's Maven repository
mavenCentral() // Maven Central repository
}
dependencies {
// Add the dependency for the Google services Gradle plugin
classpath 'com.google.gms:google-services:4.3.15'
}
}
plugins {
id 'com.android.application' version '8.0.1' apply false
id 'com.android.library' version '8.0.1' apply false
}
Archivo: build.gradle (Module:app)
plugins {
id 'com.android.application'
// Add the Google services Gradle plugin
id 'com.google.gms.google-services'
}
android {
namespace 'com.example.amstfirebaseapp'
compileSdk 33
defaultConfig {
applicationId "com.example.amstfirebaseapp"
minSdk 19
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
// Import the Firebase BoM
implementation platform('com.google.firebase:firebase-bom:32.1.0')
// TODO: Add the dependencies for Firebase products you want to use
// When using the BoM, don't specify versions in Firebase dependencies
implementation 'com.google.firebase:firebase-analytics'
// Add the dependencies for any other desired Firebase products
// https://firebase.google.com/docs/android/setup#available-libraries
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Firebase Authentication
implementation 'com.google.firebase:firebase-auth'
// Also add the dependency for the Google Play services library and specify its version
implementation 'com.google.android.gms:play-services-auth:20.5.0'
// FirebaseUI for Firebase Auth
implementation 'com.firebaseui:firebase-ui-auth:8.0.2'
//Visualizar la imagen de perfil
implementation 'com.squareup.picasso:picasso:2.8'
implementation 'com.google.firebase:firebase-database'
}
Importante: Siempre que realices cambios en los archivos Gradle, recuerda volver a sincronizar tu proyecto para asegurarte el correcto funcionamiento de las nuevas librerías. Puedes dar clic en Sync Now en la parte superior derecha de la pantalla o dar clic en File > Sync Project with Gradle files.
Pre-requisito: Habilitar el método de inicio de sesión mediante Google. Dentro de la consola del proyecto en FireBase seleccione del lado izquierdo la ruta de Build -> Authentication. Luego se mostrará el menú de Users, dar clic en el botón de Set up sign-in method y entre los proveedores adicionales habilitar Google.
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Firebase Authentication
implementation 'com.google.firebase:firebase-auth'
// Also add the dependency for the Google Play services library and specify its version
implementation 'com.google.android.gms:play-services-auth:20.5.0'
// FirebaseUI for Firebase Auth
implementation 'com.firebaseui:firebase-ui-auth:8.0.2'
}
Código de archivo: activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="59dp"
android:layout_height="54dp"
android:layout_gravity="center"
android:layout_marginTop="200px"
app:srcCompat="@drawable/google" />
<TextView
android:id="@+id/txtIniciosesion"
android:layout_width="match_parent"
android:layout_height="67dp"
android:gravity="center"
android:text="Bienvenido a AMST Firebase App"
android:textSize="24sp" />
<Button
android:id="@+id/btn_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="iniciarSesion"
android:text="Iniciar sesión" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Recordatorio: Agregar una imagen llamada google.png en src/main/res/drawable.
public class MainActivity extends AppCompatActivity {
FirebaseAuth mAuth;
GoogleSignInClient mGoogleSignInClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAuth = FirebaseAuth.getInstance();
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
Intent intent = getIntent();
String msg = intent.getStringExtra("msg");
if(msg != null){
if(msg.equals("cerrarSesion")){
cerrarSesion();
}
}
}
Importante: default_web_client_id puede llegar a mantenerse en error hasta compilar por primera vez el programa.
public void iniciarSesion(View view) {
resultLauncher.launch(new Intent(mGoogleSignInClient.getSignInIntent()));
}
ActivityResultLauncher<Intent> resultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent intent = result.getData();
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(intent);
try {
GoogleSignInAccount account = task.getResult(ApiException.class);
if (account != null) firebaseAuthWithGoogle(account);
} catch (ApiException e) {
Log.w("TAG", "Fallo el inicio de sesión con google.", e);
}
}
}
});
private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
Log.d("TAG", "firebaseAuthWithGoogle:" + acct.getId());
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(),
null);
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, task -> {
if (task.isSuccessful()) {
FirebaseUser user = mAuth.getCurrentUser();
updateUI(user);
} else {
System.out.println("error");
updateUI(null);
}
});
}
private void updateUI(FirebaseUser user) {
if (user != null) {
HashMap<String, String> info_user = new HashMap<String, String>();
info_user.put("user_name", user.getDisplayName());
info_user.put("user_email", user.getEmail());
info_user.put("user_photo", String.valueOf(user.getPhotoUrl()));
info_user.put("user_id", user.getUid());
info_user.put("user_phone", user.getPhoneNumber());
finish();
Intent intent = new Intent(this, PerfilUsuario.class);
intent.putExtra("info_user", info_user);
startActivity(intent);
} else {
System.out.println("sin registrarse");
}
}
Ahora mostraremos la información de un del usuario en una nueva actividad e implementar.
Creamos una nueva Actividad dando clic derecho en /app > New > Activity > Empty Views Activity.
Asignamos un nombre a la nueva actividad como PerfilUsuario, y damos clic en Finish.
En app/res/layout/activity_perfil_usuario.xml, diseñamos la vista para el perfil de usuario donde colocaremos la información que del cliente.
Código de archivo: activity_perfil_usuario.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".PerfilUsuario">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".PerfilUsuario">
<ImageView
android:id="@+id/imv_foto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:srcCompat="@tools:sample/avatars" />
<TextView
android:id="@+id/txt_userId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="ID" />
<TextView
android:id="@+id/txt_nombre"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Nombre de usuario"
android:textSize="30sp" />
<TextView
android:id="@+id/txt_correo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="correo"
android:textSize="18sp" />
<Button
android:id="@+id/btn_logout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="cerrarSesion"
android:text="Cerrar Sesion" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
dependencies {
//Visualizar la imagen de perfil
implementation 'com.squareup.picasso:picasso:2.8'
}
public class PerfilUsuario extends AppCompatActivity {
TextView txt_id, txt_name, txt_email;
ImageView imv_photo;
DatabaseReference db_reference;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_perfil_usuario);
Intent intent = getIntent();
HashMap<String, String> info_user = (HashMap<String, String>) intent.getSerializableExtra("info_user");
System.out.println("Informacion"+ info_user);
txt_id = findViewById(R.id.txt_userId);
txt_name = findViewById(R.id.txt_nombre);
txt_email = findViewById(R.id.txt_correo);
imv_photo = findViewById(R.id.imv_foto);
txt_id.setText(info_user.get("user_id"));
txt_name.setText(info_user.get("user_name"));
txt_email.setText(info_user.get("user_email"));
String photo = info_user.get("user_photo");
Picasso.get().load(photo).into(imv_photo);
public void cerrarSesion(View view) {
FirebaseAuth.getInstance().signOut();
finish();
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("msg", "cerrarSesion");
startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAuth = FirebaseAuth.getInstance();
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
Intent intent = getIntent();
String msg = intent.getStringExtra("msg");
if(msg != null){
if(msg.equals("cerrarSesion")){
cerrarSesion();
}
}
}
private void cerrarSesion() {
mGoogleSignInClient.signOut().addOnCompleteListener(this,
task -> updateUI(null));
}
Implementaremos una base de datos para guardar tweets de un usuario específico.
dependencies {
//Base de datos de Firebase
implementation 'com.google.firebase:firebase-database'
}
Estructura JSON
Base de datos {
Grupos {
GrupoN{
Tweets {
Hola firebase {
autor: Adriana Collaguazo,
fecha: 01-06-2023 }
}
},
Grupo1 {},
Grupo2{},
….
}
}
Se crea el siguiente árbol de estructura:
Importante: Así fue creado un árbol de estructura de forma gráfica. En los siguientes pasos se mostrará como hacerlo desde la aplicación.
public class PerfilUsuario extends AppCompatActivity {
TextView txt_id, txt_name, txt_email;
ImageView imv_photo;
DatabaseReference db_reference;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_perfil_usuario);
Intent intent = getIntent();
HashMap<String, String> info_user = (HashMap<String, String>) intent.getSerializableExtra("info_user");
System.out.println("Informacion"+ info_user);
txt_id = findViewById(R.id.txt_userId);
txt_name = findViewById(R.id.txt_nombre);
txt_email = findViewById(R.id.txt_correo);
imv_photo = findViewById(R.id.imv_foto);
txt_id.setText(info_user.get("user_id"));
txt_name.setText(info_user.get("user_name"));
txt_email.setText(info_user.get("user_email"));
String photo = info_user.get("user_photo");
Picasso.get().load(photo).into(imv_photo);
iniciarBaseDeDatos();
leerTweets();
escribirTweets(info_user.get("user_name"));
}
public void iniciarBaseDeDatos() {
db_reference = FirebaseDatabase.getInstance().getReference().child("Grupos");
}
public void leerTweets() {
db_reference.child("Grupo1").child("tweets")
.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
System.out.println(snapshot);
}
}
@Override
public void onCancelled(DatabaseError error) {
System.out.println(error.toException());
}
});
}
public void escribirTweets(String autor){
String tweet = "hola mundo firebase 2";
String fecha = "03/11/2022"; //Fecha actual
Map<String, String> hola_tweet = new HashMap<String, String>();
hola_tweet.put("autor", autor);
hola_tweet.put("fecha", fecha);
DatabaseReference tweets = db_reference.child("Grupo1").child("tweets");
tweets.setValue(tweet);
tweets.child(tweet).child("autor").setValue(autor);
tweets.child(tweet).child("fecha").setValue(fecha);
}
public void cerrarSesion(View view) {
FirebaseAuth.getInstance().signOut();
finish();
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("msg", "cerrarSesion");
startActivity(intent);
}
La práctica de laboratorio será desarrollada en el siguiente formato:
Nombre del archivo: AMST_LabA_GrupoB_Apellido1_Apellido2_Apellido3
Siendo A el número del trabajo y B el número del grupo