adicao de botao de terminar sessao

main
230421 2025-12-06 22:04:01 +00:00
parent 81eb71bd46
commit 460b719785
4 changed files with 271 additions and 6 deletions

View File

@ -1,8 +1,12 @@
package com.example.vdcscore; package com.example.vdcscore;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.view.Menu; import android.view.Menu;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.navigation.NavigationView; import com.google.android.material.navigation.NavigationView;
@ -15,6 +19,10 @@ import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import com.example.vdcscore.databinding.ActivityMainBinding; import com.example.vdcscore.databinding.ActivityMainBinding;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import java.io.InputStream;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
@ -48,6 +56,88 @@ public class MainActivity extends AppCompatActivity {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration); NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController); NavigationUI.setupWithNavController(navigationView, navController);
// Carregar dados do utilizador no menu lateral
loadUserDataInNavHeader();
}
private void loadUserDataInNavHeader() {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user == null) return;
View headerView = binding.navView.getHeaderView(0);
TextView textViewName = headerView.findViewById(R.id.textViewName);
TextView textViewEmail = headerView.findViewById(R.id.textView);
ImageView imageView = headerView.findViewById(R.id.imageView);
// Carregar nome
if (textViewName != null) {
if (user.getDisplayName() != null && !user.getDisplayName().isEmpty()) {
textViewName.setText(user.getDisplayName());
} else {
textViewName.setText("Utilizador");
}
}
// Carregar email
if (textViewEmail != null && user.getEmail() != null) {
textViewEmail.setText(user.getEmail());
}
// Carregar foto de perfil
if (imageView != null && user.getPhotoUrl() != null) {
loadProfileImageInNavHeader(user.getPhotoUrl().toString(), imageView);
} else {
// Tentar carregar do Storage
loadProfileImageFromStorage(imageView);
}
}
private void loadProfileImageInNavHeader(String imageUrl, ImageView imageView) {
new Thread(() -> {
InputStream input = null;
try {
java.net.URL url = new java.net.URL(imageUrl);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
input = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(input);
runOnUiThread(() -> {
if (bitmap != null && imageView != null) {
imageView.setImageBitmap(bitmap);
imageView.setScaleType(android.widget.ImageView.ScaleType.CENTER_CROP);
}
});
} catch (Exception e) {
// Se falhar, tentar carregar do Storage
runOnUiThread(() -> loadProfileImageFromStorage(imageView));
} finally {
if (input != null) {
try {
input.close();
} catch (Exception e) {
// Ignorar erro ao fechar
}
}
}
}).start();
}
private void loadProfileImageFromStorage(ImageView imageView) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user == null || imageView == null) return;
com.google.firebase.storage.FirebaseStorage.getInstance()
.getReference()
.child("profile_images/" + user.getUid() + ".jpg")
.getDownloadUrl()
.addOnSuccessListener(uri -> {
loadProfileImageInNavHeader(uri.toString(), imageView);
})
.addOnFailureListener(e -> {
// Manter imagem padrão
});
} }
@Override @Override
@ -63,4 +153,11 @@ public class MainActivity extends AppCompatActivity {
return NavigationUI.navigateUp(navController, mAppBarConfiguration) return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp(); || super.onSupportNavigateUp();
} }
@Override
protected void onResume() {
super.onResume();
// Atualizar dados do utilizador quando voltar à activity
loadUserDataInNavHeader();
}
} }

View File

@ -44,8 +44,11 @@ public class ContaActivity extends AppCompatActivity {
private ImageView imageProfile; private ImageView imageProfile;
private TextInputEditText editName; private TextInputEditText editName;
private TextInputEditText editImageUrl;
private TextView textEmail; private TextView textEmail;
private Button btnSaveName; private Button btnSaveName;
private Button btnLoadImageUrl;
private Button btnLogout;
private View btnChangePhoto; private View btnChangePhoto;
private View cardImageContainer; private View cardImageContainer;
@ -58,6 +61,8 @@ public class ContaActivity extends AppCompatActivity {
private ActivityResultLauncher<String> permissionLauncher; private ActivityResultLauncher<String> permissionLauncher;
private Uri selectedImageUri; private Uri selectedImageUri;
private static final String PREFS_NAME = "LoginPrefs";
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -88,8 +93,10 @@ public class ContaActivity extends AppCompatActivity {
imageProfile = findViewById(R.id.imageProfile); imageProfile = findViewById(R.id.imageProfile);
editName = findViewById(R.id.editName); editName = findViewById(R.id.editName);
editImageUrl = findViewById(R.id.editImageUrl);
textEmail = findViewById(R.id.textEmail); textEmail = findViewById(R.id.textEmail);
btnSaveName = findViewById(R.id.btnSaveName); btnSaveName = findViewById(R.id.btnSaveName);
btnLoadImageUrl = findViewById(R.id.btnLoadImageUrl);
btnLogout = findViewById(R.id.btnLogout); btnLogout = findViewById(R.id.btnLogout);
btnChangePhoto = findViewById(R.id.btnChangePhoto); btnChangePhoto = findViewById(R.id.btnChangePhoto);
cardImageContainer = findViewById(R.id.cardImageContainer); cardImageContainer = findViewById(R.id.cardImageContainer);
@ -226,11 +233,121 @@ public class ContaActivity extends AppCompatActivity {
if (btnSaveName != null) { if (btnSaveName != null) {
btnSaveName.setOnClickListener(v -> saveUserName()); btnSaveName.setOnClickListener(v -> saveUserName());
} }
if (btnLoadImageUrl != null) {
btnLoadImageUrl.setOnClickListener(v -> loadImageFromUrl());
}
if (btnLogout != null) { if (btnLogout != null) {
btnLogout.setOnClickListener(v -> logoutUser()); btnLogout.setOnClickListener(v -> logoutUser());
} }
} }
private void loadImageFromUrl() {
if (editImageUrl == null) return;
String imageUrl = editImageUrl.getText().toString().trim();
if (imageUrl.isEmpty()) {
Toast.makeText(this, "Por favor, insira uma URL válida", Toast.LENGTH_SHORT).show();
return;
}
if (!imageUrl.startsWith("http://") && !imageUrl.startsWith("https://")) {
Toast.makeText(this, "URL inválida. Deve começar com http:// ou https://", Toast.LENGTH_SHORT).show();
return;
}
progressDialog.show();
// Carregar imagem da URL
new Thread(() -> {
try {
java.net.URL url = new java.net.URL(imageUrl);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(input);
runOnUiThread(() -> {
progressDialog.dismiss();
if (bitmap != null && imageProfile != null) {
imageProfile.setImageBitmap(bitmap);
// Converter bitmap para URI e fazer upload
uploadImageFromBitmap(bitmap);
} else {
Toast.makeText(this, "Erro ao carregar imagem da URL", Toast.LENGTH_SHORT).show();
}
});
if (input != null) {
input.close();
}
} catch (Exception e) {
runOnUiThread(() -> {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao carregar imagem: " + e.getMessage(), Toast.LENGTH_SHORT).show();
});
}
}).start();
}
private void uploadImageFromBitmap(Bitmap bitmap) {
FirebaseUser user = mAuth.getCurrentUser();
if (user == null) return;
progressDialog.show();
try {
// Redimensionar se muito grande
int maxSize = 1024;
if (bitmap.getWidth() > maxSize || bitmap.getHeight() > maxSize) {
float scale = Math.min((float) maxSize / bitmap.getWidth(), (float) maxSize / bitmap.getHeight());
int newWidth = Math.round(bitmap.getWidth() * scale);
int newHeight = Math.round(bitmap.getHeight() * scale);
bitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);
byte[] imageData = baos.toByteArray();
// Upload para Firebase Storage
StorageReference profileImageRef = storageRef.child("profile_images/" + user.getUid() + ".jpg");
UploadTask uploadTask = profileImageRef.putBytes(imageData);
uploadTask.addOnSuccessListener(taskSnapshot -> {
profileImageRef.getDownloadUrl().addOnSuccessListener(uri -> {
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setPhotoUri(uri)
.build();
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
progressDialog.dismiss();
if (task.isSuccessful()) {
Toast.makeText(this, "Foto de perfil atualizada com sucesso!", Toast.LENGTH_SHORT).show();
editImageUrl.setText("");
loadProfileImage(uri.toString());
} else {
Toast.makeText(this, "Erro ao atualizar foto: " +
(task.getException() != null ? task.getException().getMessage() : "Erro desconhecido"),
Toast.LENGTH_SHORT).show();
}
});
}).addOnFailureListener(e -> {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao obter URL da imagem: " + e.getMessage(), Toast.LENGTH_SHORT).show();
});
}).addOnFailureListener(e -> {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao fazer upload: " + e.getMessage(), Toast.LENGTH_SHORT).show();
});
} catch (Exception e) {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao processar imagem: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void logoutUser() { private void logoutUser() {
// Limpar credenciais guardadas // Limpar credenciais guardadas
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE); SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);

View File

@ -107,7 +107,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:text="Alterar Foto" android:text="Alterar Foto (Galeria)"
android:textColor="#616161" android:textColor="#616161"
android:textSize="15sp" android:textSize="15sp"
android:textStyle="bold" android:textStyle="bold"
@ -116,6 +116,50 @@
android:padding="12dp" android:padding="12dp"
android:background="?attr/selectableItemBackgroundBorderless" /> android:background="?attr/selectableItemBackgroundBorderless" />
<!-- URL Input Section -->
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:hint="URL da Imagem (Google)"
app:boxCornerRadiusTopStart="12dp"
app:boxCornerRadiusTopEnd="12dp"
app:boxCornerRadiusBottomStart="12dp"
app:boxCornerRadiusBottomEnd="12dp"
app:boxStrokeWidth="1dp"
app:boxStrokeColor="#BDBDBD"
app:startIconDrawable="@android:drawable/ic_menu_view"
app:startIconTint="#616161"
app:boxBackgroundMode="outline"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/editImageUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textUri"
android:textColor="#212121"
android:textColorHint="#9E9E9E"
android:textSize="14sp"
android:padding="14dp"
android:background="@android:color/transparent"
android:hint="https://..." />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/btnLoadImageUrl"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="12dp"
android:backgroundTint="#616161"
android:text="Carregar Imagem da URL"
android:textColor="#FFFFFF"
android:textSize="14sp"
android:textStyle="bold"
android:elevation="2dp"
android:stateListAnimator="@null" />
</LinearLayout> </LinearLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>

View File

@ -14,22 +14,29 @@
<ImageView <ImageView
android:id="@+id/imageView" android:id="@+id/imageView"
android:layout_width="wrap_content" android:layout_width="80dp"
android:layout_height="wrap_content" android:layout_height="80dp"
android:contentDescription="@string/nav_header_desc" android:contentDescription="@string/nav_header_desc"
android:paddingTop="@dimen/nav_header_vertical_spacing" android:paddingTop="@dimen/nav_header_vertical_spacing"
android:scaleType="centerCrop"
android:background="#E0E0E0"
app:srcCompat="@mipmap/ic_launcher_round" /> app:srcCompat="@mipmap/ic_launcher_round" />
<TextView <TextView
android:id="@+id/textViewName"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing" android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="@string/nav_header_title" android:text="@string/nav_header_title"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" /> android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="#FFFFFF"
android:textStyle="bold" />
<TextView <TextView
android:id="@+id/textView" android:id="@+id/textView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/nav_header_subtitle" /> android:text="@string/nav_header_subtitle"
android:textColor="#FFFFFF"
android:alpha="0.9" />
</LinearLayout> </LinearLayout>