Gps
We just need to follow the 1 and 2 steps, except in Pocket PC that we will need also following the step 3.
To add GPS support to any application, we advise COPYING AND PASTING the next code with the DB structure we already have working in other projects and that it can be seen at the following collections definition:
iOS EXCLUSIVE NODES
By default, iOS uses its own Apple location services, if we want to use those from the Google ones, we must specify the two attributes which are described below.
THEY ARE ATTRIBUTES OF THE APP NODE..
ATTRIBUTE | DESCRIPTION |
---|---|
google-api-enable | true or false. By default, iOS uses the Apple service to locate the coordinates we are going to show in a contents of mapview type. If we want to use the Google APIs to show a better location and that the location be exactly the same than in Android, we should put this attribute to true. |
google-api-key | Here, we will put the API key value that Google provides us to be able to use its services, if the previous attribute is to true, here, a value we will have to specify . |
Step 1. Definition of Collections
Definition of the collections.
<!-- La SQL no se mira, simplemente hay que tener una puesta. --> <coll name="ConectarGPS" title="el conector" sql="SELECT t1.* FROM ##PREF##empresa t1" objname="ConectarGPS" updateobj="ConectarGPS" progid="ASData.CASBasicDataObj" stringkey="true" idfieldname="LONGITUD" connection="transmision" useextdata="true"> <group name="General" id="1"/> <connection name="transmision" connstring="Provider=CGSoft Remote Provider;Data Source=127.0.0.1;Port=4242;ProgID=CGSSocketCE.ConnectCE"/> <prop name="LONGITUD" visible="0" type="T" size="12"/> <prop name="LATITUD" visible="0" type="T" size="12"/> <prop name="RUMBO" visible="0" type="T" size="12"/> <prop name="FGPS" visible="0" type="T" size="12"/> <prop name="HGPS" visible="0" type="T" size="12"/> <prop name="STATUS" visible="0" type="T" size="12"/> </coll> <!-- Esta segunda colección, si los datos se graban en otra tabla, no es necesaria --> <coll name="CoordenadasGPS" title="la Coordenada" sql="SELECT c.*, u.NOMBRE AS MAP_USUARIO FROM ##PREF##coordenadasgps c LEFT OUTER JOIN ##PREF##usuarios u ON c.IDUSUARIO=u.ID" objname="coordenadasgps" updateobj="coordenadasgps" progid="ASData.CASBasicDataObj" show-map="true" sort="FECHAHORAGPS" nostopreplica="true" check-owner="false" dependent="false"> <group name="General" id="1"></group> <prop name="IDEMPRESA" visible="0" type="N" mapcol="Empresas" mapfld="ID"></prop> <prop name="IDUSUARIO" visible="0" type="N" mapcol="Usuarios" mapfld="ID"></prop> <prop name="ADDRESS" visible="7" type="T" fieldsize="30" size="100" mapview-address="true">Dirección:</prop> <prop name="DESCRIPCION" visible="7" type="T" fieldsize="30" size="100" mapview-description="true">Descripción:</prop> <prop name="LATITUDGPS" visible="0" group="1" type="N6" fieldsize="10" mapview-latitude="true" showmap-latitud="true"></prop> <prop name="LONGITUDGPS" visible="7" group="1" type="N6" fieldsize="10" mapview-longitude="true" showmap-longitud="true"></prop> <prop name="RUMBOGPS" visible="7" group="1" type="N6" fieldsize="10"></prop> <prop name="FECHAHORAGPS" visible="7" group="1" type="D" fieldsize="10" showmap-datetime="true"></prop> <prop name="FECHAHORAPDA" visible="7" group="1" type="D" fieldsize="10"></prop> <!-- no visibles --> <prop name="OPCIONES" labelwidth="7" visible="0" group="1" type="N" fieldsize="14"></prop> <prop name="OP1" visible="0" group="1" type="N" fieldsize="5">DIAS</prop> <create> <action name="setval" field="IDEMPRESA" value="##ENTID##"></action> <action name="setval" field="IDUSUARIO" value="##USERID##"></action> <action name="setval" field="FECHAHORAPDA" value="##NOW_TIME##"></action> <action name="setval" field="OPCIONES" value="0"></action> </create> </coll>
- The conectargps collection, is an special collection which gets data from the internal GPS of the device and it shows them in the form of a collection, so that we can call it at any time.
- The second collection coordenadasgps, is a collection that we use in some projects to save the data of the position, as we can see at the step 2, we use the maintenance node to save the data of the GPS position each minute in this collection, although as we have already said, we can call the conectargps collection at any time and taking its values when and how we want to, there is no reason to use this second collection or the maintenance node neither.
Step 2. Data Collection
Before the data collection, we must start the GPS of the device, for this, we are going to use the onlong and onlogoff nodes of the Companies collection, so that the GPS will start when entering at the application and it stops when we leaving it.
<onlogon> <action name="runscript"> <script language="VBScript"> AppData.UserInterface.StartGPS </script> </action> </onlogon> <onlogoff> <action name="runscript"> <script language="VBScript"> AppData.UserInterface.StopGPS </script> </action> </onlogoff>
Following, we are going to read the GPS data, for this, we are going to use the <maintenance> node, which will be within the Companies Collection .
This is an action to make the GPS reading that the PDA has, which coordinates will be saved in database.
This script is associated to the two collections described at the step 1.
Setting the period and frequency values to the desired values. .
<maintenance> <action name="Lectura GPS" type="runscript" period="X" frecuency="1" auto="true" show="false"> <script language="VBScript"> Dim collGPS,tablagps,obj Set collGPS =appdata.GetCollection("ConectarGPS") Set x =collGPS("LONGITUD") if not x is nothing then if x("STATUS")="1" then ' si status vale 1 significa que no hay error de conexion con el servicio if x("HGPS")<>"" then appdata.CurrentEnterprise.Variables("GPSError")=0 Set tablagps =appdata.GetCollection("CoordenadasGPS") Set obj =tablagps.CreateObject if x("LATITUD")<>"" then obj("LATITUDGPS") =CDbl(x("LATITUD")) if x("LONGITUD")<>"" then obj("LONGITUDGPS") =CDbl(x("LONGITUD")) if x("RUMBO")<>"" then obj("RUMBOGPS") =CDbl(x("RUMBO")) if x("FGPS")<>"" then obj("FECHAHORAGPS") =x("FGPS")+" "+x("HGPS") tablagps.AddItem Empty,obj obj.save set obj =nothing tablagps.Clear end if else 'appdata.CurrentEnterprise.Variables("GPSError")=1 'appdata.failwithmessage -11888, "Hay un problema con la configuración GPS, consulte con su proveedor antes de continuar trabajando." end if else 'appdata.writeconsolestring "GPS ERROR, x es nada" end if Set x =nothing collGPS.Clear </script> </action> </maintenance>
EXAMPLE WITH JAVASCRIPT
<maintenance> <action name="Lectura GPS" type="runscript" period="X" frecuency="1" auto="true" show="false"> <script language="javascript"> var collGPS, objCollGPS; collGPS = appData.getCollection("ConectarGPS"); collGPS.startBrowse(); try { objCollGPS = collGPS.getCurrentItem(); if (!objCollGPS) { throw "GPS no disponible. objCollGPS es: " + objCollGPS; throw "ERROR"; } if (objCollGPS.STATUS != 1) { throw "GPS no disponible. STATUS vale: " + objCollGPS.STATUS; } if (!objCollGPS.LONGITUD) { throw "Sin cobertura GPS"; } var collDataGPS = appData.getCollection("CoordenadasGPS"); var objDataGPS = collDataGPS.createObject(); collDataGPS.addItem(objDataGPS); objDataGPS.LATITUDGPS=objCollGPS.LATITUD; objDataGPS.LONGITUDGPS=objCollGPS.LONGITUD; objDataGPS.RUMBOGPS=objCollGPS.RUMBO; objDataGPS.FECHAHORAGPS=objCollGPS.FGPS+" "+objCollGPS.HGPS; objDataGPS.save(); /* self.MAP_ALTITUD = objCollGPS.ALTITUD; self.MAP_VELOCIDAD = objCollGPS.VELOCIDAD; self.MAP_STATUS = objCollGPS.STATUS; self.MAP_SATELITES = objCollGPS.SATELITES; self.MAP_FUENTE = objCollGPS.FUENTE; self.MAP_PRECISION = objCollGPS.PRECISION; */ } finally { collGPS.endBrowse(); } </script> </action> </maintenance>
STEP 3 (ONLY Windows Mobile)
GPS capture Program
The GPS module will be a xonegps.exe process. In order it boots when starting the device, or it is saved at the Start Up folder from Windows, or a direct access to that executable is created.
Data at the record
It is not necessary any key in the record for its configuration. Anyways, so that the application can be connected to the GPS module, it makes it through the ports by default, which are the 4242 for reading, and 4244 for stopping.
These can be modified from the record, but it is not necessary to modify them:
“HKLM”,“SOFTWARE\CGSoft\GPS”,“Port”,“0x00000000”,“4242” “HKLM”,“SOFTWARE\CGSoft\GPS”,“portstop”,“0x00000000”,“4244”
Data Reading
It would be a coll with the connection node, in which the connstring atribute is specified the port to read ( 4242 ) and the data source.
<coll name="ConectarGPS" stopreplica="3" sql="SELECT * FROM ##PREF##Empresa" objname="ConectarGPS" updateobj="ConectarGPS" progid="ASData.CASBasicDataObj" stringkey="true" idfieldname="LONGITUD" connection="transmision" loadall="false" withopen="true" useextdata="true" fontsize="9"> <connection name="transmision" connstring="Provider=CGSoft Remote Provider;Data Source=127.0.0.1;Port=4242;ProgID=CGSSocketCE.ConnectCE"/> <prop name="LONGITUD" visible="3" type="T" size="12"/> <prop name="LATITUD" visible="3" type="T" size="12"/> <prop name="RUMBO" visible="3" type="T" size="12"/> <prop name="FGPS" visible="3" type="D" size="12"/> <prop name="HGPS" visible="3" type="T" size="12"/> <prop name="STATUS" visible="3" type="T" size="12"/> <prop name="SATELITES" visible="3" type="N" size="12"/> <prop name="VELOCIDAD" visible="3" type="T" size="12"/> </coll>
Code from Script for the data capture:
Set collGPS=appdata.GetCollection("ConectarGPS") Set x=collGPS("LONGITUD") . . .
Stopping data reading
In this case, another coll is defined, where the stopping port is specified, the 4244.
<coll name="stopGPS" stopreplica="3" sql="" objname="stopGPS" updateobj="stopGPS" progid="ASData.CASBasicDataObj" stringkey="true" idfieldname="STATUS" connection="tstop" loadall="false" withopen="true" useextdata="true" fontsize="9"> <connection name="tstop" connstring="Provider=CGSoft Remote Provider;Data Source=127.0.0.1;Port=4244;ProgID=CGSSocketCE.ConnectCE"/> <prop name="STATUS" visible="3" type="T" size="12"/> </coll>
Script code:
Set collGPS=appdata.GetCollection("stopGPS") Set x=collGPS("STATUS") collGPS.clear collGPS = nothing . . .
Function to check the GPS status (only Android)
result = ui.CheckGPSStatus if result = 0 then ui.MsgBox "El dispositivo no tiene características de localización", "Error", 0 end if if result = 1 then ui.MsgBox "La localización precisa mediante GPS está habilitado", "Mensaje", 0 end if if result = 2 then ui.MsgBox "La localización imprecisa mediante redes WiFi está habilitada", "Mensaje", 0 end if if result = 3 then ui.MsgBox "No hay habilitado ningún método de localización", "Mensaje", 0 end if if result = -1 then ui.MsgBox "Error inesperado al comprobar características de localización", "Mensaje", 0 end if
Functions of Position Cache (only Android)
Dim a
a = ui.GetLastKnownLocation
Si el GPS está activo, devuelve una cadena con la última posición conocida, la haya capturado el framework o cualquier otro programa.
Dim a
a = ui.GetLastKnownLocationLatitude
a = ui.GetLastKnownLocationLongitude
a = ui.GetLastKnownLocationAltitude
a = ui.GetLastKnownLocationAccuracy
Same than the previous one, but it returns only the latitude, longitude, height and the accuracy of each one of these methods.
Control to check if the address is correct
Before saving any client address, for instance, we can make a validation to know if that address has a coordinates that can be get from the Google Maps API, so that we can save also the coordinates to be able to locate it easily in a map.
var dirgoogle=self.MAP_valueDIRECCION; // Texto con la dirección dirgoogle=dirgoogle.replace(/ /g,"+"); dirgoogle="https://maps.googleapis.com/maps/api/geocode/json?address=" + dirgoogle + "&key=TuAPIKeyGoogleMaps&language=es"; $http.post(dirgoogle, function(sJson) { var objRespuesta = JSON.parse(sJson); //ui.showToast(sJson); if (objRespuesta["status"]=="OK") { self.MAP_DIRECCION=self.MAP_valueDIRECCION; self.MAP_LATITUD=objRespuesta.results[0].geometry.location.lat; self.MAP_LONGITUD=objRespuesta.results[0].geometry.location.lng; self.MAP_NOHAYDIR=0; self.save(); } else { self.MAP_DIRECCION="DIRECCION-NO-VALIDA"; self.MAP_NOHAYDIR=1; self.save(); } }, function() { self.MAP_DIRECCION="DIRECCION-NO-VALIDA"; self.MAP_NOHAYDIR=1; self.save(); });
Methods that affect the GPS control
CheckGPSStatus
It indicates you the GPS current status in the device, the possible values that it return are:
value 0 | There is no GPS, it cannot be enabled. |
value 1 | It is enabled the GPS location. |
value 2 | It is enabled the location by wifi and phone networks. |
value 3 | The GPS is not enabled nor the location by wifi and phone networks. |
value 4 | The GPS location is enabled and the location by wifi and phone networks. |
value -1 | Unexpected error. |
Example:
nStatus = ui.CheckGPSStatus If nStatus = 0 then ui.ShowToast "No hay GPS, no se puede activar." End If If nStatus = 1 then ui.ShowToast "Está activada la localización por GPS." End If If nStatus = 2 then ui.ShowToast "Está activada la localización por redes wifi y de telefonía." End If If nStatus = 3 then ui.ShowToast "No está activado el GPS ni la ubicación por redes wifi y telefonía, a ver si nos lo activan." ui.AskUserForGPSPermission End If If nStatus = 4 then ui.ShowToast "Está activada la localización por GPS., a ver si nos lo activan y está activada la localización por redes wifi y de telefonía." End If If nStatus = -1 then ui.ShowToast "Error inesperado, compruebe la consola de mensajes." End If
AskUserForGPSPermission
It is useful to launch the configuration window of the GPS location in the devices.
Example:
nStatus = ui.CheckGPSStatus If nStatus = 0 then ui.ShowToast "No hay GPS, no se puede activar." End If If nStatus = 1 then ui.ShowToast "Está activada la localización por GPS." End If If nStatus = 2 then ui.ShowToast "Está activada la localización por redes wifi y de telefonía." End If If nStatus = 3 then ui.ShowToast "No está activado el GPS ni la ubicación por redes wifi y telefonía, a ver si nos lo activan." ui.AskUserForGPSPermission End If If nStatus = 4 then ui.ShowToast "Está activada la localización por GPS., a ver si nos lo activan y está activada la localización por redes wifi y de telefonía." End If If nStatus = -1 then ui.ShowToast "Error inesperado, compruebe la consola de mensajes." End If
startGps
It starts the coordinates capture, another ways of activation have been added.
startGps | They call to a node when a specified time is passed. |
Parameter 1 | Name of the node that it will call. This node is defined in the companies collection. |
Parameter 2 | Time that it will take in taking coordinates and call to the node (milliseconds). |
It modifies the behaviour level:
value 0 | The most important thing is to capture the coordinates. It is of highest availability. Value by defautl (by default). |
value 1 | It is a balance between capture and the battery. It tries to detect the best system for balancing reliability and battery. |
value 2 | It is to save battery. Besides putting the configuration of battery saving, it only executes once the callback node and it has to be the one in charge of call again the stargps. |
Example:
ui.StartGPS "callbackgps", 10000, 0 Definición del nodo en la colección empresas: <callbackgps> <action name="runscript"> <script language="vbscript"> ui.showToast "callback..." </script> </action> </callbackgps>
startGps | when the last position differs from x km of the next one. | |
Parameters | of JSON type, where the following properties are defined: | |
Property 1 | timeBetweenUpdates | Time it will take to check again if the position has been changed. |
Property 2 | minimumMetersDistanceRange | Range of km that when exceeded the coordinates collect. |
Example:
ui.startGps({ timeBetweenUpdates : 0, minimumMetersDistanceRange : 0 });