Spanish [B4A] [Tutorial] GPS

JorgeMC

Member
Licensed User
Longtime User
Para acabar el día, os traigo traducido el Tutorial Oficial GPS en Español para Basic4Android, característica muy importante en la mayoría de dispositivos Android y que gracias a Basic4Android es muy facil de programar. En este tutorial, os vamos a enseñar como mostrar la posición actual por GPS y el estado de los satelites a los que esta conectado el dispositivo Android.

gps1.png


La funcionalidad para poder acceder al GPS del dispositivo Android viene dada por la librería GPS, por lo que lo primero que tenemos que hacer es añadir una referencia a la misma.

gps2.png


Dentro de la librería GPS existen tres objetos relevantes, siendo el más importante de ellos el objeto GPS ya que es el que gestiona la conexión y los eventos del mismo. El segundo de ellos es Location (Posición), es una estructura que contiene los datos de nuestra posición. Los datos que contiene Location principalmente son las coordenadas de Latitud y Longitud, el tiempo y la Altitud a la que nos encontramos, recordando de nuevo que todos ellos dependen de la cobertura GPS que tengamos en ese momento. Con el objeto Location se incluyen también otras funcionalidades con las que podemos calcular la distancia entre dos rutas distintas, entre nuestra posición y otro punto, el cambio de las coordenadas a otros formatos, etc..

Aunque normalmente se utiliza con eventos el objeto Location, como pueda ser LocationChanged (Si hemos cambiado de lugar), también se puede utilizar tal y como dijimos, para calcular rutas entre dos puntos sin tener que estar en funcionamiento el GPS (Que no la librería).

El tercer y último objeto relevante es GPSSatellite, donde podemos obtener el estado de los satélites.

Volviendo al objeto GPS, este debe de ser declarado en Process_Global, ya que si no en caso contrario, deberemos de declararlo cada vez que vayamos a utilizarlo.

El primer paso es iniciar el objeto GPS, utilizando el parámetro Initialize.

Aquí un ejemplo completo sacado del tutorial original:


PHP:
Sub Process_Globals
Dim GPS1 As GPS
End Sub

Sub Globals
Dim lblLon As Label
Dim lblLat As Label
Dim lblSpeed As Label
Dim lblSatellites As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
If FirstTime Then
GPS1.Initialize("GPS")
End If
Activity.LoadLayout("1")
End Sub

Sub Activity_Resume
If GPS1.GPSEnabled = False Then
ToastMessageShow("Please enable the GPS device.", True)
StartActivity(GPS1.LocationSettingsIntent) 'Will open the relevant settings screen.
Else
GPS1.Start(0, 0) 'Listen to GPS with no filters.
End If
End Sub

Sub Activity_Pause (UserClosed As Boolean)
GPS1.Stop
End Sub

Sub GPS_LocationChanged (Location1 As Location)
lblLat.Text = "Lat = " & Location1.ConvertToMinutes(Location1.Latitude)
lblLon.Text = "Lon = " & Location1.ConvertToMinutes(Location1.Longitude)
lblSpeed.Text = "Speed = " & Location1.Speed
End Sub

Sub GPS_UserEnabled (Enabled As Boolean)
ToastMessageShow("GPS device enabled = " & Enabled, True)
End Sub

Sub GPS_GpsStatus (Satellites As List)
lblSatellites.Text = "Satellites:" & CRLF
For i = 0 To Satellites.Size - 1
Dim Satellite As GPSSatellite
Satellite = Satellites.Get(i)
lblSatellites.Text = lblSatellites.Text & CRLF & Satellite.Prn & _
" " & Satellite.Snr & " " & Satellite.UsedInFix & " " & Satellite.Azimuth _
& " " & Satellite.Elevation
Next
End Sub


El siguiente paso es decirle al GPS que se "ponga a escuchar los datos", por lo que hemos creado el evento LocatedChanged para ello. Recordar que el GPS activado de continuo puede consumir excesiva batería, y que para ello nos recomiendan utilizar tanto Activity_Resume como Activity_Pause.

También nos recuerdan que el usuario ha podido desactivar el GPS bien por temas de consumo, como de privacidad, por lo que nos recomiendan preguntar al usuario en el caso de que se encuentre desactivado si quiere activarlo, esto se hace con el siguiente código:


PHP:
Sub Activity_Resume
If GPS1.GPSEnabled = False Then
ToastMessageShow("Please enable the GPS device.", True)
StartActivity(GPS1.LocationSettingsIntent) 'Will open the relevant settings screen.
Else
GPS1.Start(0, 0) 'Listen to GPS with no filters.
End If
End Sub

Si el GPS esta activa este comenzara a procesar / escuchar los datos, los que obtiene de dos valores, minimum time (milisegundos) y minimum distance (metros), generándose un evento cuando uno de los dos ha cambiado de valor (Cosa que podemos aprovechar para ahorrar batería en nuestro programa de alguna manera).


El objeto GPS plantea / tiene tres eventos:


  1. GPS_LocationChanged (Location1 As Location): Evento principal, contiene los datos de la nueva localización.
  2. GPS_GpsStatus (Satellites As List):Este evento permite mostrar información sobre los satélites actualmente disponibles. Tenemos que tener en cuenta que no todos los satélites en la lista son realmente utilizados para el cálculo del ejemplo anterior. Por lo tanto, es posible que la lista se incluyen varios satélites, pero la recepción no es lo suficientemente bueno para una buena localización.
  3. GPS_UserEnabled (Enabled As Boolean): Este evento se produce cuando el usuario cambia el estado del dispositivo GPS.



 

Attachments

  • Tutorial GPS.zip
    6.3 KB · Views: 1,460
Last edited:

iliberis

Member
Licensed User
Longtime User
Estupendo!!! Ya tenemos otro tutorial!!! Y nada menos que el del GPS.

Asi da gusto. Pronto tendremos aqui una enciclopedia más que un foro.

Venga! Una chincheta para este tema!!! Que lo vea todo el mundo!!!
 

iliberis

Member
Licensed User
Longtime User
Gracias a ti iliberis por el trabajo que haces ;)
Hacemos, hacemos. Que si esto está empezando a levantarse, es porque estamos ya unos cuantos escribiendo mensajes y ayudando con los tutoriales. Y que siga asi mucho tiempo. Entre todos estamos consiguiendo lo unico que le falta a este lenguaje: una comunidad estable.
 

CROFG

Member
Licensed User
Longtime User
GRACIAS con mayúscula

Con esta ayuda se nos hace cada vez más fácil aprovechar los recursos que tienen los equipos Android
 

joseanquiles

Member
Licensed User
Longtime User
Hola a todos.
Voy a aprovechar para haceros una pregunta sobre el GPS.
Si lo creéis necesario, pongo esta pregunta en un nuevo post.

Quiero hacer un programita muy sencillo con un único botón :)
Cuando se pulsa ese botón envío un SMS (o mail o lo que sea, esto me da igual) con la posición actual recibida del GPS.
Lo que he hecho es basarme en el tutorial que ha traducido jorgemc. Pero claro, ese ejemplo está pensado para una recepción continua de posiciones, por ejemplo adecuado para un programa de navegación. Pero a mí no me vale, porque yo necesito la posición actual lo más rápidamente posible.

Esta es la filosofía de mi programa: cuando la actividad empieza (Resume) hago el start del GPS (como en el tutorial) y en cada evento voy almacenando la posición en una variable (en Globals, no en Process_Globals). Así, al pulsar el botón cojo la última posición almacenada y la envío. Hasta aquí todo parece razonable.
Pero no, ya que el usuario no lleva encendida continuamente mi aplicación, sino que la arranca y pulsa el botón para enviar la posición. En ese caso, como el GPS tarda un rato (largo relativamente) en posicionar, pues hay que esperar bastante hasta que entra el evento de posición del GPS y se puede enviar.
La pregunta es ¿hay alguna forma de tener rápidamente la posición? Aunque no sea exacta. Pero que permita obtener una posición aproximada en muy poco tiempo.
O quizás la filosofía del programa debería ser otra...
¿Qué opináis?
Gracias a todos por adelantado.
 

JorgeMC

Member
Licensed User
Longtime User
Es muy fácil en principio, te paso un ejemplo para que veas:

B4X:
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   Dim GPS1 As GPS
   Dim lon, lat As String
   Dim SMTP As SMTP
   
End Sub
B4X:
Sub Activity_Create(FirstTime As Boolean)
   GPS1.Initialize("GPS")
   GPS1.Start(0, 0)
   Location1.Initialize
End Sub

B4X:
Sub GPS_LocationChanged (Location1 As Location)
   
   lon = Location1.ConvertToSeconds(Location1.Longitude)
   lat= Location1.ConvertToSeconds(Location1.Latitude)
   SMTP.Initialize("smtp.gmail.com", 465, "[email protected]", "tupassword", "SMTP")
    SMTP.UseSSL = True 
   SMTP.To.Add("[email protected]")
    SMTP.Subject = "MENSAJE DE ALERTA DE MOVIL"
    SMTP.Body = "La localizacion del movil +34XXXXXXXXX es Longitud: "& Location1.ConvertToSeconds(Location1.Longitude)&" y Latitud: "& Location1.ConvertToSeconds(Location1.Latitude)
    SMTP.Send
   
   
End Sub

Te lo escrito más o menos de memoria, pero te tendría que funcionar. Con lo que te e puesto, cada vez que cambie la posición te envía un correo, ahora solo tienes que cambiar ese evento por el del click del button que quieres, manteniendo únicamente esta parte del código para que almacene los datos de la posición:

B4X:
Sub GPS_LocationChanged (Location1 As Location)
   
   lon = Location1.ConvertToSeconds(Location1.Longitude)
   lat= Location1.ConvertToSeconds(Location1.Latitude)
   
   
End Sub



Si no te sale pon el código por aquí que te ayudamos.

Saludos ;)
 

joseanquiles

Member
Licensed User
Longtime User
Muchas gracias jorgemc.
Me viene muy bien tu ejemplo.
El problema es que no es eso exactamente lo que necesito (creo que me expliqué fatal ayer).
En resumen, quiero hacer una aplicación que la arranques, pulsas un botón y envía un mail con tu posición. Y todo esto en el mínimo tiempo posible.
He hecho una prueba con el código que has puesto y funciona, pero con varios problemas (para lo que yo necesito):
1. Tienes que estar en un lugar al aire libre para que se posicione el GPS
2. Tarda un rato en posicionarse
Por eso estoy buscando una solución que rápidamente pueda enviar una localización aproximada. O que se pueda obtener la última localización que se obtuvo en el móvil.
He visto que existe la librería ABWifi, pero no sé si es para esto...
¿Se te ocurre alguna solución?

De nuevo, gracias jorgemc.
 

JorgeMC

Member
Licensed User
Longtime User
OK, miro la librería esa y lo que podemos hacer es utilizarla con un timer y una condición, me explico:

Pulsas Botón -> Le damos 5 / 10 segundillos para ver si el GPS localiza -> Aquí entra la condición, si lat & lon = 0, que tire de la librería que comentas (No se lo que tardara esa librería).
 

joseanquiles

Member
Licensed User
Longtime User
Hola Jorge,
yo ya la he estado probando esta mañana, y creo que he resuelto el problema.
Digo "creo" porque no estoy seguro.

Hago lo siguiente:

1-Cargo la librería ABWifi en mi proyecto
2-Variables globales de proceso:

Dim myWifi As ABWifi

3-Callback de pulsación del botón para localizar

Dim r As Boolean
r = myWifi.ABGetLocation("WIFI")
If r = False Then
ToastMessageShow("No se puede enviar localización:" & myWifi.ABWifiLastError,False)
Else
ToastMessageShow("Localizando posición actual...",False)
' Cuando se fije la posición entrará el callback de WIFI
End If

4-Callback del wWIFI (entra cuando localiza)

Sub WIFI_FoundLocation()
Dim location As ABFoundLocation
location = myWifi.ABGetFoundLocation()
' El objeto location contiene la longitud y la latitud
' Enviar la localización por mail, SMS, etc
End Sub


Funciona bastante bien, ya que consigue localizar en 3 ó 4 segundos en interiores (no he probado en exteriores todavía).

SIENTO tener que meter el código fuente a lo bruto, a ver si aprendo a meterlo cómo hiciste en el mensaje anterior :)
 

joseanquiles

Member
Licensed User
Longtime User
Gracias Jorge.
La próxima vez lo pondré en bonito.
Por cierto, lo de la localización con ABWifi va bastante bien, aunque hay que tener en cuenta que coge la última localización que se haya conseguido en el móvil. No es malo, pero hay que tenerlo en cuenta,
 

VDHinferm

New Member
Licensed User
Longtime User
¿Alguien sabe qué datum se usa para las coordenadas geográficas?
¿Hay alguna librería para la conversión de coordenadas en diferentes datums?
¿Hay posibilidad de usar coordendas UTM?

Si no existe nada de esto podría ser un proyecto muy interesante llevarlo a cabo.

Un saludo.
 

marbellapc

Member
Licensed User
Longtime User
Buenas que tal, se que esto tiene mucho tiempo y a lo mejor ni tendria que haberlo puesto aqui, pero como va relacionado, he creido conveniente ponerlo.

Os cuento, he bajado el ejemplo y le he metido el envio de correo con la modificacion hecha JorgeMC, el problema es que claro envia tropecientos mil correos...

Mi pregunta es, hay alguna forma de ponerle un retraso?? o mas bien un reloj que envie la posicion cada 5, 10 o 15 segundos??

Y si fuera asi, podriais orientarme, es que no se como buscarlo en el foro.

Saludos y gracias de antemano.
 

JorgeMC

Member
Licensed User
Longtime User
Podrías usar dos cosas, tampoco soy un experto así que seguro que hay otras maneras:

1º Que compruebe que si la nueva Latitud y Longitud son iguales a las anterior no haga nada.

2º Un timer cada XX segundos (En las balizas GPS se suele poner cada 15 segundos o 30) e igual que el anterior, que si es el mismo, que no envíe nada.
 

marbellapc

Member
Licensed User
Longtime User
Gracias JorgeMC, probare lo del timer, ya que los grados, minutos y segundos no cambian, pero las decimas aun estando sin moverse en lo alto de la mesa el dispositivo, van cambiando...

Asi que optare por el timer, ya que es para integrarlo en un vehiculo y que esas coordenadas las envie a una web que recoje los datos y lo muestra en un mapa, asi que me valdria un refresco de 10 o 15 segundos.

Saludos y de nuevo muchisimas gracias.
 

JorgeMC

Member
Licensed User
Longtime User
Gracias JorgeMC, probare lo del timer, ya que los grados, minutos y segundos no cambian, pero las decimas aun estando sin moverse en lo alto de la mesa el dispositivo, van cambiando...

Asi que optare por el timer, ya que es para integrarlo en un vehiculo y que esas coordenadas las envie a una web que recoje los datos y lo muestra en un mapa, asi que me valdria un refresco de 10 o 15 segundos.

Saludos y de nuevo muchisimas gracias.

Me interesa saber como guardas los datos en el server, ya que yo no soy capaz via web que lo almacene a MySQL y aparte que luego hay otro problema, cuando no tiene conexión, por ejemplo por cobertura, como lo hacemos para que esos datos los almacene y luego los vuelva a enviar ?

Saludos !!
 

marbellapc

Member
Licensed User
Longtime User
Buenas, lo de recoger los datos, es algo con lo que todavia me estoy peleando, ya que no se muy bien como hacerlo, por el mismo tema que estas comentando perdida de cobertura y demas cosas que pueden fallar.

Ayer hablando con mi colega, el se esta encargando de la parte del servidor y todo el currelo de mostrar datos en los mapas, me comento que como es para unas lineas de autobuses, se va a encargar (bueno de hecho lo tiene ya integrado) de como son rutas predefinidas, pues si perdiera la señal, segun la velocidad y el tiempo medio, simularia la marcha hasta que tuviera otra vez cobertura.

Como te digo es todo experimental, no se que es lo que saldra, de momento como te digo me sigo peleando con el gps para ver como enviar las coordenadas a una pagina web, y ya una vez me las muestre alli, la recogeria el programa y mostraria la posicion del vehiculo.

De todas formas, si consigo hacerlo funcionar lo publicare por aqui, mi mayor problema es que he realizado algunas aplicaciones sencillas, como por ejemplo para el club de airsoft y algunas mas, pero nunca me habia metido con datos GPS, ni tener que enviar datos a una web, mas bien las aplicaciones que he hecho hasta ahora recogian datos de mysql y los mostraba, asi que como digo a ver que sale...

Saludos
 

marbellapc

Member
Licensed User
Longtime User
Buenas JorgeMC, he conseguido que desde la aplicacion llamando a un archivo PHP me escriba en la base de datos, el unico problema es que me inserta los campos vacios.

He utilizado HttpUtils, HttpUtils Service, por ir probando cosas, ya que mi socio esta muy liado con otros proyectos y no ha podido hacer nada, aparte de que el programa en .NET

He declarado en Process_Globals lo siguiente:
B4X:
Dim PostUrl                As String 
PostUrl = "http://10.1.0.25/android_maps/send_coord.php"

Y luego en GPS_LocationChanged
B4X:
HttpUtils.PostString("", PostUrl, "?gpsName=Captura&gpsLat="&Lat&"&gpsLon="&Lon)

Para que el resultado fuera este:
HTML:
http://10.1.0.25/android_maps/send_coord.php?gpsName=Captura&gpsLat="&Lat&"&gpsLon="&Lon

Pero como digo me inserta un registro pero vacio, alguno sabe o a podido solucionar esto, es que por mas vueltas que he estado dando por los foros, no consiguo ver ningun ejemplo que sea de insertar, todos los que veo son para leer.

Saludos y gracias de antemano.
 

Attachments

  • Portapapeles01.jpg
    Portapapeles01.jpg
    59 KB · Views: 818
Top