adicao de botao de terminar sessao
parent
81eb71bd46
commit
460b719785
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
@ -57,6 +60,8 @@ public class ContaActivity extends AppCompatActivity {
|
||||||
private ActivityResultLauncher<Intent> imagePickerLauncher;
|
private ActivityResultLauncher<Intent> imagePickerLauncher;
|
||||||
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) {
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
Loading…
Reference in New Issue