a localizaçao esta funcionando + ou - certo

This commit is contained in:
2026-03-12 17:16:29 +00:00
parent fba454ce01
commit 86221e5179
5 changed files with 68 additions and 57 deletions

View File

@@ -18,12 +18,12 @@
<targets>
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=rogmvsfmmfus95e6" />
<DeviceId pluginId="LocalEmulator" identifier="path=/Users/230408/.android/avd/Pixel_9_Pro.avd" />
</handle>
</Target>
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="LocalEmulator" identifier="path=/Users/230408/.android/avd/Pixel_9_Pro.avd" />
<DeviceId pluginId="LocalEmulator" identifier="path=/Users/230408/.android/avd/Pixel_9_Pro_filho.avd" />
</handle>
</Target>
</targets>

View File

@@ -4,16 +4,23 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<queries>
<package android:name="com.google.android.gms" />
<intent>
<action android:name="com.google.android.geo.API_KEY" />
</intent>
</queries>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
@@ -22,12 +29,17 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.PAP_FindU">
android:theme="@style/Theme.PAP_FindU"
tools:targetApi="34">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyAxen212OKqkfpu1AbWajLGTCTSdRhJWlM" />
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<service
android:name=".LocationService"
android:enabled="true"
@@ -37,9 +49,11 @@
<activity
android:name=".CriarConta"
android:exported="false" />
<activity
android:name=".Recuperar_Passe"
android:exported="false" />
<activity
android:name=".ChatActivity"
android:exported="false" />
@@ -56,6 +70,7 @@
<activity
android:name=".AddZoneActivity"
android:exported="false" />
<activity
android:name=".MainActivity"
android:exported="true"
@@ -64,6 +79,7 @@
<activity
android:name=".EditProfileActivity"
android:exported="false" />
<activity
android:name=".SecurityActivity"
android:exported="false" />

View File

@@ -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<String, Object> 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) {

View File

@@ -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 {

View File

@@ -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();
}
}