We only need to follow the steps 1 and 2, except in Pocket PC, that we need besides the step 3.

For adding GPS support to any application, we advise COPY AND PASTE the next code, with the DB structure that we have already working in other projects and that can be seen in the definition of the following collections:

iOS EXCLUSIVE NODES

By default, iOS uses its own Apple location services, if we want to use those ones from Google, we must specify the two attributes described bellow. THEY ARE APP NODE ATTRIBUTES.

ATTRIBUTEDESCRIPTION
google-api-enabletrue or false. By default, iOS uses the Apple services to locate the coordinates we are going to display in a contents of the MapView type. If we want touse the Google API for a better location and that the location be exactly the same than in Android, we must put this attribute to true.
google-api-keyHere, 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 we must specify a value.



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 a specialcollection that gets the data from the internal GPS of the device and shows them in the form of the collection, so that we can call it any time.


  • The second collection CoordenadasGPS, is a collection that we use in some projects to save the position data, as we will see at the step 2, we use the maintenance node to save the GPS position data each minute in this collection, although as we said before, we can call the ConectarGPS collection at any time and take its values when and how we want to, there is no reason to use this second collection or the maintenance node.



Before the data collection, we must start the device GPS, for this, we are going to use the onlogon and onlogoff nodes of the Companies collection, so that the GPS starts when entering the application and stops when we leave 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>


Next, we are going to take the GPS data reading, for this, we are going to use the maintenance node, that will be inside 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 values of the period and frequency 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")&lt;&gt;"" then
					appdata.CurrentEnterprise.Variables("GPSError")=0
					Set tablagps =appdata.GetCollection("CoordenadasGPS")
					Set obj =tablagps.CreateObject
					if x("LATITUD")&lt;&gt;"" then obj("LATITUDGPS") =CDbl(x("LATITUD"))
					if x("LONGITUD")&lt;&gt;"" then obj("LONGITUDGPS") =CDbl(x("LONGITUD"))
					if x("RUMBO")&lt;&gt;"" then obj("RUMBOGPS") =CDbl(x("RUMBO"))
					if x("FGPS")&lt;&gt;"" 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>   	




The GPS module will be a process, XOneGPS.exe. For booting when starting the device, or it is saved at the Start Up folder from Windows, or a direct access is created to that executable.


No key is necessary in the record for its configuration. Anyways, in order the application can be connected to the GPS module, it is done through the ports by default which are the 4242 for reading, and the 4244 for stopping.

These ones 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”



It would be a coll with the <connection> node, in which the connstring attribute is specified the port for reading ( 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 data capturing:

     Set collGPS=appdata.GetCollection("ConectarGPS")
     Set x=collGPS("LONGITUD")
            . . .



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


result = ui.CheckGPSStatus
if result = 0 then
	ui.MsgBox "El dispositivo no tiene hardware 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 (Android only)


Dim a
a = ui.GetLastKnownLocation


If the GPS is active, it returns a string with the last known position, has been captured by the framework or by any other program.

Dim a
a = ui.GetLastKnownLocationLatitude
a = ui.GetLastKnownLocationLongitude
a = ui.GetLastKnownLocationAltitude
a = ui.GetLastKnownLocationAccuracy


The same than the previous one, but they return only the latitude, longitude, altitude and the accuracy of each one of these methods.