From 7aa8b7900927868afcd19ce599c269e36d365b40 Mon Sep 17 00:00:00 2001 From: 230415 <230415@epvc.pt> Date: Wed, 10 Dec 2025 10:19:08 +0000 Subject: [PATCH] =?UTF-8?q?recupera=C3=A7=C3=A3o=20de=20passe=20e=20uns=20?= =?UTF-8?q?erritos=20no=20google?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 1 + .../example/lifegrid/CriarContaActivity.java | 70 +++++++++++++- .../com/example/lifegrid/LoginActivity.java | 76 ++++++++++++++- .../lifegrid/RecupearPasswordActivity.java | 94 +++++++++++++++++++ .../main/res/layout/activity_criar_conta.xml | 4 +- .../res/layout/activity_recupear_password.xml | 20 +++- app/src/main/res/values/strings.xml | 2 + gradle/libs.versions.toml | 2 + 8 files changed, 258 insertions(+), 11 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a15fd02..bbce542 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -44,6 +44,7 @@ dependencies { implementation(libs.googleid) implementation(libs.firebase.database) implementation(libs.recyclerview) + implementation(libs.play.services.auth) testImplementation(libs.junit) androidTestImplementation(libs.ext.junit) androidTestImplementation(libs.espresso.core) diff --git a/app/src/main/java/com/example/lifegrid/CriarContaActivity.java b/app/src/main/java/com/example/lifegrid/CriarContaActivity.java index d3c142e..b5958ff 100644 --- a/app/src/main/java/com/example/lifegrid/CriarContaActivity.java +++ b/app/src/main/java/com/example/lifegrid/CriarContaActivity.java @@ -11,14 +11,24 @@ import android.widget.ProgressBar; import android.widget.Toast; import androidx.activity.EdgeToEdge; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import com.google.android.gms.auth.api.signin.GoogleSignIn; +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; +import com.google.android.gms.auth.api.signin.GoogleSignInClient; +import com.google.android.gms.auth.api.signin.GoogleSignInOptions; +import com.google.android.gms.common.api.ApiException; +import com.google.android.gms.tasks.Task; import com.google.firebase.FirebaseApp; +import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.auth.GoogleAuthProvider; public class CriarContaActivity extends AppCompatActivity { @@ -30,6 +40,7 @@ public class CriarContaActivity extends AppCompatActivity { private Button googleButton2; private ProgressBar loadingProgressBar; private FirebaseAuth firebaseAuth; + private GoogleSignInClient googleSignInClient; @Override protected void onCreate(Bundle savedInstanceState) { @@ -53,10 +64,15 @@ public class CriarContaActivity extends AppCompatActivity { FirebaseApp.initializeApp(this); firebaseAuth = FirebaseAuth.getInstance(); + // Configurar Google Sign-In + GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestIdToken(getString(R.string.default_web_client_id)) + .requestEmail() + .build(); + googleSignInClient = GoogleSignIn.getClient(this, gso); + loginButton2.setOnClickListener(v -> criarConta()); - googleButton2.setOnClickListener(v -> - Toast.makeText(this, "Login com Google disponível em breve.", Toast.LENGTH_SHORT).show() - ); + googleButton2.setOnClickListener(v -> signInWithGoogle()); } private void criarConta() { @@ -163,6 +179,54 @@ public class CriarContaActivity extends AppCompatActivity { return true; } + private void signInWithGoogle() { + Intent signInIntent = googleSignInClient.getSignInIntent(); + googleSignInLauncher.launch(signInIntent); + } + + private final ActivityResultLauncher googleSignInLauncher = registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), + result -> { + if (result.getResultCode() == RESULT_OK) { + Task task = GoogleSignIn.getSignedInAccountFromIntent(result.getData()); + try { + GoogleSignInAccount account = task.getResult(ApiException.class); + firebaseAuthWithGoogle(account.getIdToken()); + } catch (ApiException e) { + Toast.makeText(this, "Erro ao criar conta com Google: " + e.getMessage(), Toast.LENGTH_LONG).show(); + } + } else { + Toast.makeText(this, "Criação de conta com Google cancelada.", Toast.LENGTH_SHORT).show(); + } + } + ); + + private void firebaseAuthWithGoogle(String idToken) { + toggleLoading(true); + AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null); + firebaseAuth.signInWithCredential(credential) + .addOnCompleteListener(this, task -> { + toggleLoading(false); + if (task.isSuccessful()) { + FirebaseUser user = firebaseAuth.getCurrentUser(); + String welcome = user != null && !TextUtils.isEmpty(user.getDisplayName()) + ? "Conta criada com sucesso! Bem-vindo, " + user.getDisplayName() + : "Conta criada com Google com sucesso!"; + Toast.makeText(this, welcome, Toast.LENGTH_SHORT).show(); + + // Redirecionar para TelaInicialActivity após criação bem-sucedida + Intent intent = new Intent(CriarContaActivity.this, TelaInicialActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + finish(); + } else { + Toast.makeText(this, + task.getException() != null ? task.getException().getMessage() : "Falha ao criar conta com Google", + Toast.LENGTH_LONG).show(); + } + }); + } + private void toggleLoading(boolean show) { loadingProgressBar.setVisibility(show ? View.VISIBLE : View.GONE); loginButton2.setEnabled(!show); diff --git a/app/src/main/java/com/example/lifegrid/LoginActivity.java b/app/src/main/java/com/example/lifegrid/LoginActivity.java index a3515ee..4790b12 100644 --- a/app/src/main/java/com/example/lifegrid/LoginActivity.java +++ b/app/src/main/java/com/example/lifegrid/LoginActivity.java @@ -12,14 +12,24 @@ import android.widget.TextView; import android.widget.Toast; import androidx.activity.EdgeToEdge; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import com.google.android.gms.auth.api.signin.GoogleSignIn; +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; +import com.google.android.gms.auth.api.signin.GoogleSignInClient; +import com.google.android.gms.auth.api.signin.GoogleSignInOptions; +import com.google.android.gms.common.api.ApiException; +import com.google.android.gms.tasks.Task; import com.google.firebase.FirebaseApp; +import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.auth.GoogleAuthProvider; public class LoginActivity extends AppCompatActivity { @@ -36,6 +46,8 @@ public class LoginActivity extends AppCompatActivity { private TextView ouTextView; private ProgressBar loadingProgressBar; private FirebaseAuth firebaseAuth; + private GoogleSignInClient googleSignInClient; + private static final int RC_SIGN_IN = 9001; @Override protected void onCreate(Bundle savedInstanceState) { @@ -63,6 +75,13 @@ public class LoginActivity extends AppCompatActivity { FirebaseApp.initializeApp(this); firebaseAuth = FirebaseAuth.getInstance(); + // Configurar Google Sign-In + GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestIdToken(getString(R.string.default_web_client_id)) + .requestEmail() + .build(); + googleSignInClient = GoogleSignIn.getClient(this, gso); + loginButton.setOnClickListener(v -> validarLogin()); criarContaTextView.setOnClickListener(new View.OnClickListener() { @Override @@ -74,13 +93,16 @@ public class LoginActivity extends AppCompatActivity { passesquecerTextView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { + String email = emailEditText.getText().toString().trim(); Intent intent = new Intent(LoginActivity.this, RecupearPasswordActivity.class); + // Passar o email digitado no login para a atividade de recuperação + if (!TextUtils.isEmpty(email)) { + intent.putExtra("email", email); + } startActivity(intent); } }); - googleButton.setOnClickListener(v -> - Toast.makeText(this, "Login com Google disponível em breve.", Toast.LENGTH_SHORT).show() - ); + googleButton.setOnClickListener(v -> signInWithGoogle()); } private void validarLogin() { @@ -168,6 +190,54 @@ public class LoginActivity extends AppCompatActivity { return true; } + private void signInWithGoogle() { + Intent signInIntent = googleSignInClient.getSignInIntent(); + googleSignInLauncher.launch(signInIntent); + } + + private final ActivityResultLauncher googleSignInLauncher = registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), + result -> { + if (result.getResultCode() == RESULT_OK) { + Task task = GoogleSignIn.getSignedInAccountFromIntent(result.getData()); + try { + GoogleSignInAccount account = task.getResult(ApiException.class); + firebaseAuthWithGoogle(account.getIdToken()); + } catch (ApiException e) { + Toast.makeText(this, "Erro ao fazer login com Google: " + e.getMessage(), Toast.LENGTH_LONG).show(); + } + } else { + Toast.makeText(this, "Login com Google cancelado.", Toast.LENGTH_SHORT).show(); + } + } + ); + + private void firebaseAuthWithGoogle(String idToken) { + toggleLoading(true); + AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null); + firebaseAuth.signInWithCredential(credential) + .addOnCompleteListener(this, task -> { + toggleLoading(false); + if (task.isSuccessful()) { + FirebaseUser user = firebaseAuth.getCurrentUser(); + String welcome = user != null && !TextUtils.isEmpty(user.getDisplayName()) + ? "Bem-vindo, " + user.getDisplayName() + : "Login com Google realizado com sucesso!"; + Toast.makeText(this, welcome, Toast.LENGTH_SHORT).show(); + + // Redirecionar para TelaInicialActivity após login bem-sucedido + Intent intent = new Intent(LoginActivity.this, TelaInicialActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + finish(); + } else { + Toast.makeText(this, + task.getException() != null ? task.getException().getMessage() : "Falha no login com Google", + Toast.LENGTH_LONG).show(); + } + }); + } + private void toggleLoading(boolean show) { loadingProgressBar.setVisibility(show ? View.VISIBLE : View.GONE); loginButton.setEnabled(!show); diff --git a/app/src/main/java/com/example/lifegrid/RecupearPasswordActivity.java b/app/src/main/java/com/example/lifegrid/RecupearPasswordActivity.java index a1b9afc..7a4e20f 100644 --- a/app/src/main/java/com/example/lifegrid/RecupearPasswordActivity.java +++ b/app/src/main/java/com/example/lifegrid/RecupearPasswordActivity.java @@ -1,6 +1,13 @@ package com.example.lifegrid; import android.os.Bundle; +import android.text.TextUtils; +import android.util.Patterns; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ProgressBar; +import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; @@ -8,8 +15,16 @@ import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import com.google.firebase.FirebaseApp; +import com.google.firebase.auth.FirebaseAuth; + public class RecupearPasswordActivity extends AppCompatActivity { + private EditText emailEditText4; + private Button loginButton3; + private ProgressBar loadingProgressBar; + private FirebaseAuth firebaseAuth; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -20,5 +35,84 @@ public class RecupearPasswordActivity extends AppCompatActivity { v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); + + emailEditText4 = findViewById(R.id.emailEditText4); + loginButton3 = findViewById(R.id.loginButton3); + loadingProgressBar = findViewById(R.id.loadingProgressBar); + + FirebaseApp.initializeApp(this); + firebaseAuth = FirebaseAuth.getInstance(); + + // Receber o email passado do LoginActivity e pré-preencher o campo + String emailPassado = getIntent().getStringExtra("email"); + if (!TextUtils.isEmpty(emailPassado)) { + emailEditText4.setText(emailPassado); + // Tornar o campo não editável quando vier do login + emailEditText4.setEnabled(false); + emailEditText4.setFocusable(false); + emailEditText4.setClickable(false); + } + + loginButton3.setOnClickListener(v -> recuperarPassword()); + } + + private void recuperarPassword() { + String email = emailEditText4.getText().toString().trim(); + String emailPassado = getIntent().getStringExtra("email"); + + // Validar email + if (TextUtils.isEmpty(email)) { + emailEditText4.setError("Email obrigatório."); + emailEditText4.requestFocus(); + return; + } + + if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) { + emailEditText4.setError("Formato de email inválido."); + emailEditText4.requestFocus(); + return; + } + + // Se o email veio do login, garantimos que é o mesmo (campo já está desabilitado) + // Não precisa validar novamente, pois o campo não pode ser modificado + + toggleLoading(true); + + // Enviar email de recuperação de senha + firebaseAuth.sendPasswordResetEmail(email) + .addOnCompleteListener(this, task -> { + toggleLoading(false); + if (task.isSuccessful()) { + // Email enviado com sucesso + Toast.makeText(this, + "Email de recuperação enviado para " + email + "\nVerifique sua caixa de entrada.", + Toast.LENGTH_LONG).show(); + // Limpar o campo após sucesso + emailEditText4.setText(""); + } else { + // Erro ao enviar email + String errorMessage = "Erro ao enviar email de recuperação."; + if (task.getException() != null) { + errorMessage = task.getException().getMessage(); + // Traduzir alguns erros comuns para português + if (errorMessage.contains("user-not-found")) { + errorMessage = "Nenhuma conta encontrada com este email."; + } else if (errorMessage.contains("invalid-email")) { + errorMessage = "Formato de email inválido."; + } else if (errorMessage.contains("network")) { + errorMessage = "Erro de conexão. Verifique sua internet."; + } else if (errorMessage.contains("too-many-requests")) { + errorMessage = "Muitas tentativas. Tente novamente mais tarde."; + } + } + Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show(); + } + }); + } + + private void toggleLoading(boolean show) { + loadingProgressBar.setVisibility(show ? View.VISIBLE : View.GONE); + loginButton3.setEnabled(!show); + emailEditText4.setEnabled(!show); } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_criar_conta.xml b/app/src/main/res/layout/activity_criar_conta.xml index 805af91..258fdb8 100644 --- a/app/src/main/res/layout/activity_criar_conta.xml +++ b/app/src/main/res/layout/activity_criar_conta.xml @@ -12,9 +12,9 @@ android:id="@+id/logoImageView" android:layout_width="213dp" android:layout_height="97dp" - android:layout_marginTop="76dp" + android:layout_marginTop="56dp" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.073" + app:layout_constraintHorizontal_bias="0.08" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/logo" /> diff --git a/app/src/main/res/layout/activity_recupear_password.xml b/app/src/main/res/layout/activity_recupear_password.xml index 99cf01d..d986d9a 100644 --- a/app/src/main/res/layout/activity_recupear_password.xml +++ b/app/src/main/res/layout/activity_recupear_password.xml @@ -3,6 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main" + android:background="#FFFFFF" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".RecupearPasswordActivity"> @@ -48,10 +49,11 @@ @@ -79,4 +81,16 @@ app:layout_constraintHorizontal_bias="0.425" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView8" /> + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 033f83d..4d9788b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,5 @@ LifeGrid + + YOUR_WEB_CLIENT_ID_HERE \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d1a07b3..e7efd6a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,6 +14,7 @@ credentialsPlayServicesAuth = "1.5.0" googleid = "1.1.1" firebaseDatabase = "22.0.1" recyclerview = "1.4.0" +playServicesAuth = "21.2.0" [libraries] junit = { group = "junit", name = "junit", version.ref = "junit" } @@ -29,6 +30,7 @@ credentials-play-services-auth = { group = "androidx.credentials", name = "crede googleid = { group = "com.google.android.libraries.identity.googleid", name = "googleid", version.ref = "googleid" } firebase-database = { group = "com.google.firebase", name = "firebase-database", version.ref = "firebaseDatabase" } recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" } +play-services-auth = { group = "com.google.android.gms", name = "play-services-auth", version.ref = "playServicesAuth" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }