From 8fb4ceef955f48e7f7c415aff18f220e247dfe03 Mon Sep 17 00:00:00 2001
From: 230415 <230415@epvc.pt>
Date: Wed, 3 Dec 2025 10:33:52 +0000
Subject: [PATCH] Login e Criar conta
---
.idea/.gitignore | 3 +
.idea/AndroidProjectSystem.xml | 6 +
.idea/compiler.xml | 6 +
.idea/deploymentTargetSelector.xml | 10 +
.idea/deviceManager.xml | 13 ++
.idea/gradle.xml | 19 ++
.idea/migrations.xml | 10 +
.idea/misc.xml | 10 +
.idea/runConfigurations.xml | 17 ++
.idea/studiobot.xml | 6 +
.idea/vcs.xml | 6 +
app/build.gradle.kts | 7 +
app/google-services.json | 29 +++
app/src/main/AndroidManifest.xml | 8 +
.../example/lifegrid/CriarContaActivity.java | 24 +++
.../com/example/lifegrid/LoginActivity.java | 147 +++++++++++++++
.../lifegrid/RecupearPasswordActivity.java | 24 +++
.../main/res/layout/activity_criar_conta.xml | 178 ++++++++++++++++++
app/src/main/res/layout/activity_login.xml | 145 +++++++-------
.../res/layout/activity_recupear_password.xml | 10 +
build.gradle.kts | 1 +
gradle/libs.versions.toml | 14 ++
22 files changed, 630 insertions(+), 63 deletions(-)
create mode 100644 .idea/.gitignore
create mode 100644 .idea/AndroidProjectSystem.xml
create mode 100644 .idea/compiler.xml
create mode 100644 .idea/deploymentTargetSelector.xml
create mode 100644 .idea/deviceManager.xml
create mode 100644 .idea/gradle.xml
create mode 100644 .idea/migrations.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/runConfigurations.xml
create mode 100644 .idea/studiobot.xml
create mode 100644 .idea/vcs.xml
create mode 100644 app/google-services.json
create mode 100644 app/src/main/java/com/example/lifegrid/CriarContaActivity.java
create mode 100644 app/src/main/java/com/example/lifegrid/RecupearPasswordActivity.java
create mode 100644 app/src/main/res/layout/activity_criar_conta.xml
create mode 100644 app/src/main/res/layout/activity_recupear_password.xml
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml
new file mode 100644
index 0000000..4a53bee
--- /dev/null
+++ b/.idea/AndroidProjectSystem.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..b86273d
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
new file mode 100644
index 0000000..b268ef3
--- /dev/null
+++ b/.idea/deploymentTargetSelector.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/deviceManager.xml b/.idea/deviceManager.xml
new file mode 100644
index 0000000..91f9558
--- /dev/null
+++ b/.idea/deviceManager.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..639c779
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/migrations.xml b/.idea/migrations.xml
new file mode 100644
index 0000000..f8051a6
--- /dev/null
+++ b/.idea/migrations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..74dd639
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..16660f1
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/studiobot.xml b/.idea/studiobot.xml
new file mode 100644
index 0000000..539e3b8
--- /dev/null
+++ b/.idea/studiobot.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 6496c1d..a15fd02 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,5 +1,6 @@
plugins {
alias(libs.plugins.android.application)
+ alias(libs.plugins.google.gms.google.services)
}
android {
@@ -37,6 +38,12 @@ dependencies {
implementation(libs.material)
implementation(libs.activity)
implementation(libs.constraintlayout)
+ implementation(libs.firebase.auth)
+ implementation(libs.credentials)
+ implementation(libs.credentials.play.services.auth)
+ implementation(libs.googleid)
+ implementation(libs.firebase.database)
+ implementation(libs.recyclerview)
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
diff --git a/app/google-services.json b/app/google-services.json
new file mode 100644
index 0000000..c40df5d
--- /dev/null
+++ b/app/google-services.json
@@ -0,0 +1,29 @@
+{
+ "project_info": {
+ "project_number": "1019731295596",
+ "project_id": "lifegrid-f6692",
+ "storage_bucket": "lifegrid-f6692.firebasestorage.app"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:1019731295596:android:7170262ae018291b00c749",
+ "android_client_info": {
+ "package_name": "com.example.lifegrid"
+ }
+ },
+ "oauth_client": [],
+ "api_key": [
+ {
+ "current_key": "AIzaSyAbQ_-mob81SR07481CSJHP_z3GniS-xdk"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": []
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 98f4e71..a5fcac4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,8 @@
+
+
+
+
diff --git a/app/src/main/java/com/example/lifegrid/CriarContaActivity.java b/app/src/main/java/com/example/lifegrid/CriarContaActivity.java
new file mode 100644
index 0000000..d0b0c40
--- /dev/null
+++ b/app/src/main/java/com/example/lifegrid/CriarContaActivity.java
@@ -0,0 +1,24 @@
+package com.example.lifegrid;
+
+import android.os.Bundle;
+
+import androidx.activity.EdgeToEdge;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.graphics.Insets;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsCompat;
+
+public class CriarContaActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ EdgeToEdge.enable(this);
+ setContentView(R.layout.activity_criar_conta);
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
+ Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
+ return insets;
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/lifegrid/LoginActivity.java b/app/src/main/java/com/example/lifegrid/LoginActivity.java
index 078370a..d29b8ba 100644
--- a/app/src/main/java/com/example/lifegrid/LoginActivity.java
+++ b/app/src/main/java/com/example/lifegrid/LoginActivity.java
@@ -1,6 +1,15 @@
package com.example.lifegrid;
+import android.content.Intent;
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.TextView;
+import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
@@ -8,8 +17,26 @@ 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;
+import com.google.firebase.auth.FirebaseUser;
+
public class LoginActivity extends AppCompatActivity {
+ private TextView textView5;
+ private TextView textView1;
+ private TextView criarContaTextView;
+ private TextView emailTextView;
+ private EditText emailEditText;
+ private TextView passTextView;
+ private EditText passwordEditText;
+ private TextView passesquecerTextView;
+ private Button loginButton;
+ private Button googleButton;
+ private TextView ouTextView;
+ private ProgressBar loadingProgressBar;
+ private FirebaseAuth firebaseAuth;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -20,6 +47,126 @@ public class LoginActivity extends AppCompatActivity {
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
+ textView5 = findViewById(R.id.textView5);
+ textView1 = findViewById(R.id.textView1);
+ criarContaTextView = findViewById(R.id.criarContaTextView);
+ emailTextView = findViewById(R.id.emailTextView);
+ emailEditText = findViewById(R.id.emailEditText);
+ passTextView = findViewById(R.id.passTextView);
+ passwordEditText = findViewById(R.id.passwordEditText);
+ passesquecerTextView = findViewById(R.id.passesquecerTextView);
+ loginButton = findViewById(R.id.loginButton);
+ googleButton = findViewById(R.id.googleButton);
+ ouTextView = findViewById(R.id.ouTextView);
+ loadingProgressBar = findViewById(R.id.loadingProgressBar);
+ FirebaseApp.initializeApp(this);
+ firebaseAuth = FirebaseAuth.getInstance();
+
+ loginButton.setOnClickListener(v -> validarLogin());
+ criarContaTextView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(LoginActivity.this, CriarContaActivity.class);
+ startActivity(intent);
+ }
+ });
+ passesquecerTextView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(LoginActivity.this, RecupearPasswordActivity.class);
+ startActivity(intent);
+ }
+ });
+ googleButton.setOnClickListener(v ->
+ Toast.makeText(this, "Login com Google disponível em breve.", Toast.LENGTH_SHORT).show()
+ );
+ }
+
+ private void validarLogin() {
+ String email = emailEditText.getText().toString().trim();
+ String password = passwordEditText.getText().toString();
+
+ if (!validarEspaços(email, password)) {
+ return;
+ }
+
+ toggleLoading(true);
+
+ firebaseAuth.signInWithEmailAndPassword(email, password)
+ .addOnCompleteListener(this, task -> {
+ toggleLoading(false);
+ if (task.isSuccessful()) {
+ FirebaseUser user = task.getResult().getUser();
+ String welcome = user != null && !TextUtils.isEmpty(user.getEmail())
+ ? "Bem-vindo, " + user.getEmail()
+ : "Login realizado com sucesso!";
+ Toast.makeText(this, welcome, Toast.LENGTH_LONG).show();
+ } else {
+ Toast.makeText(this,
+ task.getException() != null ? task.getException().getMessage() : "Falha no login",
+ Toast.LENGTH_LONG).show();
+ }
+ });
+ }
+
+ private void recupearPassword() {
+ String email = emailEditText.getText().toString().trim();
+ if (TextUtils.isEmpty(email)) {
+ emailEditText.setError("Informe o email para recuperar a palavra-passe.");
+ emailEditText.requestFocus();
+ return;
+ }
+
+ toggleLoading(true);
+ firebaseAuth.sendPasswordResetEmail(email)
+ .addOnCompleteListener(this, task -> {
+ toggleLoading(false);
+ if (task.isSuccessful()) {
+ Toast.makeText(this,
+ "Email de recuperação enviado para " + email,
+ Toast.LENGTH_LONG).show();
+ } else {
+ Toast.makeText(this,
+ task.getException() != null ? task.getException().getMessage() : "Erro ao enviar email",
+ Toast.LENGTH_LONG).show();
+ }
+ });
+ }
+
+ private boolean validarEspaços(String email, String password) {
+ if (TextUtils.isEmpty(email)) {
+ emailEditText.setError("Email obrigatório.");
+ emailEditText.requestFocus();
+ return false;
+ }
+
+ if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
+ emailEditText.setError("Formato de email inválido.");
+ emailEditText.requestFocus();
+ return false;
+ }
+
+ if (TextUtils.isEmpty(password)) {
+ passwordEditText.setError("Palavra-passe obrigatória.");
+ passwordEditText.requestFocus();
+ return false;
+ }
+
+ if (password.length() < 6) {
+ passwordEditText.setError("Mínimo de 6 caracteres.");
+ passwordEditText.requestFocus();
+ return false;
+ }
+
+ return true;
+ }
+
+ private void toggleLoading(boolean show) {
+ loadingProgressBar.setVisibility(show ? View.VISIBLE : View.GONE);
+ loginButton.setEnabled(!show);
+ googleButton.setEnabled(!show);
+ criarContaTextView.setEnabled(!show);
+ passesquecerTextView.setEnabled(!show);
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/lifegrid/RecupearPasswordActivity.java b/app/src/main/java/com/example/lifegrid/RecupearPasswordActivity.java
new file mode 100644
index 0000000..a1b9afc
--- /dev/null
+++ b/app/src/main/java/com/example/lifegrid/RecupearPasswordActivity.java
@@ -0,0 +1,24 @@
+package com.example.lifegrid;
+
+import android.os.Bundle;
+
+import androidx.activity.EdgeToEdge;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.graphics.Insets;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsCompat;
+
+public class RecupearPasswordActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ EdgeToEdge.enable(this);
+ setContentView(R.layout.activity_recupear_password);
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
+ Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
+ return insets;
+ });
+ }
+}
\ 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
new file mode 100644
index 0000000..6e549d0
--- /dev/null
+++ b/app/src/main/res/layout/activity_criar_conta.xml
@@ -0,0 +1,178 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
index 85ccdc9..baf1204 100644
--- a/app/src/main/res/layout/activity_login.xml
+++ b/app/src/main/res/layout/activity_login.xml
@@ -5,33 +5,71 @@
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:backgroundTint="#FFFFFF"
+ android:background="#FFFFFF"
+ android:padding="24dp"
tools:context=".LoginActivity">
+
+
+
+
+
+
-
-
@@ -105,44 +133,35 @@
android:id="@+id/passesquecerTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
+ android:layout_marginTop="12dp"
android:text="Esqueceu-se a palavra passe?"
- android:textSize="11dp"
+ android:textSize="13sp"
app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passwordEditText" />
-
-
-
-
+ android:layout_marginTop="32dp"
+ android:text="Não tens conta? Clica aqui"
+ android:textColor="#121111"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/ouTextView" />
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_recupear_password.xml b/app/src/main/res/layout/activity_recupear_password.xml
new file mode 100644
index 0000000..42ddf10
--- /dev/null
+++ b/app/src/main/res/layout/activity_recupear_password.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 3756278..c4f8066 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,4 +1,5 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
+ alias(libs.plugins.google.gms.google.services) apply false
}
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 1bcc061..d1a07b3 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -7,6 +7,13 @@ appcompat = "1.7.1"
material = "1.13.0"
activity = "1.11.0"
constraintlayout = "2.2.1"
+googleGmsGoogleServices = "4.4.4"
+firebaseAuth = "24.0.1"
+credentials = "1.5.0"
+credentialsPlayServicesAuth = "1.5.0"
+googleid = "1.1.1"
+firebaseDatabase = "22.0.1"
+recyclerview = "1.4.0"
[libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" }
@@ -16,7 +23,14 @@ appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "a
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
+firebase-auth = { group = "com.google.firebase", name = "firebase-auth", version.ref = "firebaseAuth" }
+credentials = { group = "androidx.credentials", name = "credentials", version.ref = "credentials" }
+credentials-play-services-auth = { group = "androidx.credentials", name = "credentials-play-services-auth", version.ref = "credentialsPlayServicesAuth" }
+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" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
+google-gms-google-services = { id = "com.google.gms.google-services", version.ref = "googleGmsGoogleServices" }