diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
index 3b4d6bd..ac5ee25 100644
--- a/.idea/deploymentTargetSelector.xml
+++ b/.idea/deploymentTargetSelector.xml
@@ -18,12 +18,12 @@
-
+
-
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9a9057d..dd316b9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,16 +4,23 @@
-
+
-
-
+
+
+
+
+
+
+
+
+
+ android:theme="@style/Theme.PAP_FindU"
+ tools:targetApi="34">
+
+
+
+
@@ -56,6 +70,7 @@
+
+
diff --git a/app/src/main/java/com/example/pap_findu/LocationService.java b/app/src/main/java/com/example/pap_findu/LocationService.java
index fb295b9..730a43a 100644
--- a/app/src/main/java/com/example/pap_findu/LocationService.java
+++ b/app/src/main/java/com/example/pap_findu/LocationService.java
@@ -14,6 +14,7 @@ import android.location.Location;
import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
+import android.util.Log; // Importação adicionada
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -26,9 +27,7 @@ import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.Priority;
-// IMPORTAÇÕES ADICIONADAS PARA A AUTENTICAÇÃO AUTOMÁTICA
-import com.google.firebase.auth.FirebaseAuth;
-import com.google.firebase.auth.FirebaseUser;
+// Importações do Firebase
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
@@ -55,15 +54,14 @@ public class LocationService extends Service {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
// =================================================================
- // AUTOMAÇÃO: Vai buscar o ID do Filho que está logado neste telemóvel
+ // AUTOMAÇÃO: Vai buscar o código de 6 dígitos salvo no Login
// =================================================================
- FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
+ String childCode = getSharedPreferences("FindU_Prefs", MODE_PRIVATE)
+ .getString("child_access_code", null);
- if (currentUser != null) {
- String myUid = currentUser.getUid(); // Pega o ID único gerado pelo Firebase
-
- // Cria a referência da base de dados usando este ID dinâmico
- databaseReference = FirebaseDatabase.getInstance().getReference("users/" + myUid + "/live_location");
+ if (childCode != null) {
+ // Cria a pasta usando o código de 6 dígitos (ex: users/484981/live_location)
+ databaseReference = FirebaseDatabase.getInstance().getReference("users/" + childCode + "/live_location");
}
}
@@ -97,7 +95,7 @@ public class LocationService extends Service {
}
} catch (Exception e) {
- // Se o sistema operativo forçar uma paragem (muito comum em emuladores), apanhamos o erro aqui!
+ Log.e("LocationService", "Erro ao iniciar Foreground Service: " + e.getMessage());
e.printStackTrace();
stopSelf();
}
@@ -123,7 +121,7 @@ public class LocationService extends Service {
locationData.put("longitude", location.getLongitude());
locationData.put("last_updated", System.currentTimeMillis());
- // Verifica se o utilizador não é nulo antes de enviar para o Firebase
+ // Verifica se a referência não é nula antes de enviar para o Firebase
if (databaseReference != null) {
databaseReference.setValue(locationData);
}
@@ -131,11 +129,22 @@ public class LocationService extends Service {
}
};
- // Outro try-catch de segurança para a comunicação com os serviços do Google (GMS)
+ // MELHORIA AQUI: Try-catch mais abrangente para lidar com o erro de "Broker"
try {
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper());
- } catch (SecurityException e) {
- e.printStackTrace();
+ } catch (Exception e) {
+ Log.e("LocationService", "Erro crítico nos Google Play Services (Broker): " + e.getMessage());
+
+ // Plano B: Tenta obter pelo menos a última localização conhecida
+ fusedLocationClient.getLastLocation().addOnSuccessListener(location -> {
+ if (location != null && databaseReference != null) {
+ Map locationData = new HashMap<>();
+ locationData.put("latitude", location.getLatitude());
+ locationData.put("longitude", location.getLongitude());
+ locationData.put("last_updated", System.currentTimeMillis());
+ databaseReference.setValue(locationData);
+ }
+ });
}
}
@@ -154,7 +163,7 @@ public class LocationService extends Service {
NotificationChannel channel = new NotificationChannel(
"LocationChannel",
"Monitoramento de Localização",
- NotificationManager.IMPORTANCE_LOW // Low para não fazer barulho nem vibrar
+ NotificationManager.IMPORTANCE_LOW
);
NotificationManager manager = getSystemService(NotificationManager.class);
if (manager != null) {
diff --git a/app/src/main/java/com/example/pap_findu/login_activity.java b/app/src/main/java/com/example/pap_findu/login_activity.java
index 114cfaf..b2679af 100644
--- a/app/src/main/java/com/example/pap_findu/login_activity.java
+++ b/app/src/main/java/com/example/pap_findu/login_activity.java
@@ -1,6 +1,7 @@
package com.example.pap_findu;
import android.content.Intent;
+import android.content.SharedPreferences; // <-- Importação adicionada automaticamente
import android.os.Bundle;
import android.text.InputType;
import android.text.TextUtils;
@@ -196,6 +197,14 @@ public class login_activity extends AppCompatActivity {
// 1. Invalida o código para ninguém usar de novo
db.collection("login_codes").document(code).update("used", true);
+ // =======================================================
+ // 2. NOVA LINHA: GUARDA O CÓDIGO NA MEMÓRIA DO TELEMÓVEL!
+ // =======================================================
+ getSharedPreferences("FindU_Prefs", MODE_PRIVATE)
+ .edit()
+ .putString("child_access_code", code)
+ .apply();
+
Toast.makeText(this, "Conectado como Filho!", Toast.LENGTH_SHORT).show();
goToMainActivity();
} else {
diff --git a/app/src/main/java/com/example/pap_findu/ui/map/MapFragment.java b/app/src/main/java/com/example/pap_findu/ui/map/MapFragment.java
index 22a387f..db44db4 100644
--- a/app/src/main/java/com/example/pap_findu/ui/map/MapFragment.java
+++ b/app/src/main/java/com/example/pap_findu/ui/map/MapFragment.java
@@ -31,7 +31,7 @@ import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.google.firebase.firestore.FirebaseFirestore;
-import com.google.firebase.firestore.QuerySnapshot;
+import com.google.firebase.firestore.QueryDocumentSnapshot;
public class MapFragment extends Fragment implements OnMapReadyCallback {
@@ -41,13 +41,11 @@ public class MapFragment extends Fragment implements OnMapReadyCallback {
private FirebaseFirestore db;
private FirebaseAuth auth;
- // Variáveis para o Mapa e Tempo Real
private GoogleMap mMap;
private Marker childMarker;
private DatabaseReference locationRef;
private ValueEventListener locationListener;
- // VARIÁVEL ADICIONADA PARA GUARDAR O ID DA CRIANÇA AUTOMATICAMENTE
private String currentChildId = null;
public View onCreateView(@NonNull LayoutInflater inflater,
@@ -83,7 +81,7 @@ public class MapFragment extends Fragment implements OnMapReadyCallback {
if (user == null) return;
if (user.isAnonymous()) {
- if (btnAddChild != null) btnAddChild.setVisibility(View.GONE);
+ // Se o utilizador é anónimo (Filho), ele vê o próprio mapa
showMapState();
return;
}
@@ -102,18 +100,15 @@ public class MapFragment extends Fragment implements OnMapReadyCallback {
.addOnCompleteListener(task -> {
if (task.isSuccessful() && task.getResult() != null && !task.getResult().isEmpty()) {
- // =================================================================
- // AUTOMAÇÃO: Encontra a criança e extrai o ID dela!
- // =================================================================
+ // Pegamos no código de acesso do primeiro filho encontrado
var document = task.getResult().getDocuments().get(0);
- // MUITO IMPORTANTE: Mude "uid" para o nome do campo na sua base de dados que tem o ID do filho!
- currentChildId = document.getString("uid");
+ // USAMOS O accessCode COMO CHAVE DE LIGAÇÃO
+ currentChildId = document.getString("accessCode");
if (currentChildId != null) {
- showMapState(); // Se encontrou o ID, carrega o mapa
+ showMapState();
} else {
- Toast.makeText(getContext(), "Erro: Criança encontrada, mas sem ID.", Toast.LENGTH_SHORT).show();
showEmptyState();
}
} else {
@@ -140,21 +135,15 @@ public class MapFragment extends Fragment implements OnMapReadyCallback {
@Override
public void onMapReady(@NonNull GoogleMap googleMap) {
mMap = googleMap;
-
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(0, 0), 2f));
- // Inicia a escuta APENAS se tivermos encontrado um ID válido
if (currentChildId != null) {
startListeningToChildLocation();
- } else {
- Toast.makeText(getContext(), "A aguardar ligação à criança...", Toast.LENGTH_SHORT).show();
}
}
private void startListeningToChildLocation() {
- // =================================================================
- // AUTOMAÇÃO: Usa a variável currentChildId em vez de texto fixo
- // =================================================================
+ // Escuta na pasta baseada no Código de Acesso
locationRef = FirebaseDatabase.getInstance().getReference("users/" + currentChildId + "/live_location");
locationListener = new ValueEventListener() {
@@ -168,25 +157,18 @@ public class MapFragment extends Fragment implements OnMapReadyCallback {
LatLng childPosition = new LatLng(lat, lng);
if (childMarker == null) {
- MarkerOptions markerOptions = new MarkerOptions()
- .position(childPosition)
- .title("Criança");
-
- childMarker = mMap.addMarker(markerOptions);
- mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(childPosition, 16f));
+ childMarker = mMap.addMarker(new MarkerOptions().position(childPosition).title("Filho"));
+ mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(childPosition, 15f));
} else {
childMarker.setPosition(childPosition);
- mMap.animateCamera(CameraUpdateFactory.newLatLng(childPosition));
}
}
- } else {
- Log.w("MapFragment", "Pasta de localização vazia ou inexistente para o ID: " + currentChildId);
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
- Log.e("MapFragment", "Erro ao ler localização: " + error.getMessage());
+ Log.e("MapFragment", "Erro: " + error.getMessage());
}
};
@@ -214,18 +196,13 @@ public class MapFragment extends Fragment implements OnMapReadyCallback {
private void showCodeDialog(String code) {
if (getContext() == null) return;
-
ClipboardManager clipboard = (ClipboardManager) requireContext().getSystemService(Context.CLIPBOARD_SERVICE);
- ClipData clip = ClipData.newPlainText("Código", code);
- clipboard.setPrimaryClip(clip);
- Toast.makeText(getContext(), "Código copiado!", Toast.LENGTH_SHORT).show();
+ clipboard.setPrimaryClip(ClipData.newPlainText("Código", code));
new AlertDialog.Builder(getContext())
.setTitle("Filho Adicionado!")
- .setMessage("O código de acesso é: " + code + "\n\n(Já copiado automaticamente)")
- .setCancelable(false)
+ .setMessage("O código de acesso é: " + code)
.setPositiveButton("Ir para o Mapa", (dialog, which) -> checkIfHasChildren())
- .setNegativeButton("Adicionar Outro", (dialog, which) -> dialog.dismiss())
.show();
}
}
\ No newline at end of file