Como sabéis las coordenadas que establece el GPS de vuestro dispositivo son el resultado de complejos cálculos matemáticos que se realizan en función de la señal de los satélites que capta, estas coordenadas pueden tener una precisión de centímetros (si se utiliza GPS diferencial) aunque lo normal es que la precisión para uso civil sea de varios metros.
Para calcular la posición se necesita como mínimo la información de 3 satélites, para ello cada uno envía su id y la hora de su reloj interno y en base a estos datos el GPS calcula el tiempo que tarda en llegar la señal; posteriormente utilizando un método matemático llamado trilateración inversa calcula la latitud y longitud de tu posición.
Android nos proporciona una serie de procedimientos que nos informan de los parámetros de cada satélite: elevación, azimut, nivel de ruido de la señal, etc...
Realmente no es tan sencillo como pudiera parecer inicialmente llegar a estos datos ya que además de utilizar el servicio del sistema "LOCATION_SERVICE" hay que configurar la clase tGPSListener que automáticamente genera eventos que nos avisan del instante en el que el GPS se activa, se desactiva, del tiempo del primer "fix", y -lo que nos interesa en este caso- cada vez que se recopile información de los satélites, que se hace mediante el disparo del evento "GPS_EVENT_SATELLITE_STATUS".
Una vez que se dispare capturaremos los datos de esta forma:
satelites := FLocationManager.getGpsStatus(NIL).getSatellites;
Después recorreremos "satelites" para obtener la información asociada a cada uno de ellos tecleando lo siguiente:
satelite := tjgpssatellite.wrap((Objeto AS ILocalObject).GetObjectID);
con lo que obtendremos:
satelite.getAzimut() : el azimut del satélite en grados
satelite.getElevation() : la elevacion en grados
satelite.getPrn: Un número pseudo aleatorio
satelite.getSnr: El ruido de la señal
satelite.hasAlmanac(): si tiene datos de almanaque
satelie.hasEphemeris(): si tiene datos de efemérides
satelite.usedInFix(): si se usa para fijar la posición
El procedimiento que he utilizado es el siguiente:
....
tform1 = class(tform)
..VARIABLES..;
PROCEDURE onGpsStatusChanged(event: Integer);
PROCEDURE IniciarGPS;
PUBLIC
{ Public declarations }
Lock: TCriticalSection;
PRIVATE
{ Private declarations }
satelites: jIterable;
FLocationManager: JLocationManager;
locationListener: TLocationListener;
LocationManagerService: JObject;
END; //tform1
// Definimos la clase TGpsListener
TGpsListener = CLASS(TJavaLocal, JGpsStatus_Listener)
PRIVATE
FParent: Tform1;
PUBLIC
CONSTRUCTOR Create(AParent: Tform1);
PROCEDURE onGpsStatusChanged(event: Integer); CDECL;
END;
CONSTRUCTOR TGpsListener.Create(AParent: TfGPS);
BEGIN
INHERITED Create;
FParent := AParent;
END;
PROCEDURE TGpsListener.onGpsStatusChanged(event: Integer);
BEGIN
FParent.onGpsStatusChanged(event);
END;
....
PROCEDURE tform1.IniciarGPS;
BEGIN
LocationManagerService := tAndroidHelper.context.getSystemService(TJContext.JavaClass.LOCATION_SERVICE);
FLocationManager := TJLocationManager.wrap((LocationManagerService AS ILocalObject).GetObjectID);
GPSListener := TGpsListener.Create(self);
END;
PROCEDURE tform1.onGpsStatusChanged(event: Integer);
VAR
satelite: jgpssatellite;
Objeto: JObject;
iter: jiterator;
BEGIN
IF Event = Tjgpsstatus.JavaClass.GPS_EVENT_STARTED THEN
BEGIN
// Mostrarmensaje('event started');
END;
IF Event = Tjgpsstatus.JavaClass.GPS_EVENT_STOPPED THEN
BEGIN
// Mostrarmensaje('event stopped');
END;
IF Event = Tjgpsstatus.JavaClass.Gps_event_first_fix THEN
BEGIN
IF Assigned(FLocationManager) THEN
BEGIN
TiempoParaElFirstFix := Int((Fgps.FLocationManager.GetGpsStatus(NIL).GetTimeToFirstFix) / 1000).ToString;
// Mostrarmensaje('event first fix');
END;
END;
//SI SE DISPARA EL EVENTO gps_event_satellite_status...
IF Event = Tjgpsstatus.JavaClass.GPS_EVENT_SATELLITE_STATUS THEN
BEGIN
Lock.Acquire;
TRY
IF Assigned(FLocationManager) THEN
BEGIN
IF FLocationManager.IsProviderEnabled(TJLocationManager.JavaClass.GPS_PROVIDER) THEN
BEGIN
MisSatelites := Fgps.FLocationManager.GetGpsStatus(NIL).GetSatellites;
Satelites := Fgps.FLocationManager.GetGpsStatus(NIL).GetSatellites;
Micontador := 0;
Micontadorfix := 0;
// contar satelites
IF MisSatelites "esDistintoA" NIL THEN
BEGIN
Iter := Fgps.MisSatelites.Iterator;
// RECORRO LA LISTA UNO A UNO PARA OBTENER SUS CARACTERISTICAS
Objeto := NIL;
WHILE Iter.Hasnext DO
BEGIN
Objeto := Iter.Next;
IF Assigned(Objeto) THEN
BEGIN
Inc(Micontador);
Satelite := Tjgpssatellite.Wrap((Objeto AS ILocalObject).GetObjectID);
//Ojo, no confundir la variable satelites:JIterable con satelite: jgpssatellite
IF Satelite "esDistintoA" NIL THEN
BEGIN
IF Satelite.UsedInFix THEN
BEGIN
Inc(Micontadorfix);
END;
END;
END;
END;
END;
ContadorSat := Micontadorfix.Tostring + '/' + Micontador.Tostring;
END;
END;
FINALLY
Lock.Release;
END;
END;
END;
...
en el onClose
añadir
IF Assigned(Lock) THEN
Lock.Free;
En la app GPS TOTAL RUN en el menú "Satélites" tenéis un ejemplo de como quedaría todo lo expuesto anteriormente.
Buen aporte,
ResponderEliminartengo problemas con el form [TfGPS] no entiendo donde lo has creado,
agradecería una ayuda: franciscogc88@gmail.com
El form tfGPS es el nombre del form principal de la aplicación que he usado para probar lo de los satélites.
ResponderEliminarSi tu form principal es "form1" tendrías que cambiar "tfGPS" por "tForm1"
Hola necesito ayuda para obtener la ubicacion actual del dispositivo movil algun ejemplo que me proporcionen, de antemano agradezco su atencion.
ResponderEliminarhola como estas? todo me funcionó perfecto el código pero...nunca se dispara el evento onGpsStatusChanged, no se que me estará faltando, aclaro que además uso LocationSensor (componente de delphi) dentro del mismo formulario, saludos!
ResponderEliminar