Esta entrada corresponde a la continuación del artículo Creando un Punto de Interés con Realidad Aumentada en Wikitude Parte 1; en el cual definimos lo que es un Punto de Interés o POI, algunas consideraciones sobre el uso del GPS en un dispositivo Android y definimos parte del Architect World (código JavaScript) empleado para manejar los Puntos de Interés en base a la ubicación del dispositivo.
Creación de la plataforma cruzada para mostrar Puntos de Interés
Ya introduciendo esta entrada, veremos cómo vincular nuestro Architect World (código JavaScript) con el código nativo (código Java) de la aplicación para obtener y actualizar constantemente los Puntos de Interés según la posición del dispositivo:
El código nativo (Java)
Nuestra activity en Android se encargará de obtener la posición del dispositivo al transcurrir un tiempo determinado o desplazarse cierta distancia; una vez que obtenida la posición del dispositivo, la activity invocará un método JavaScript llamado locationChangedFn(lat, lon, alt, acc)
que recibe como parámetros la localización del usuario (latitud, longitud, altitud y precisión).
El Architect World (código JavaScript)
Una vez invocado el método locationChangedFn(lat, lon, alt, acc)
, el mismo se encargará de invocar a las funciones necesarias para obtener los Puntos de Interés cercanos en base a la posición (longitud, latitud y altitud) del dispositivo y de renderizarlos en la pantalla del dispositivo.
Posibilidades Architect World (código JavaScript) para obtener Puntos de Interés cercanos dado la posición del dispositivo
Al ser código web, existen múltiples formas en la que podemos obtener los Puntos de Interés que hayamos definidos según la posición del usuario:
Podemos invocar al método architectView.callJavaScript() para pasar modelos de datos de nuestro código Java hacia el JavaScript; este método permite crear una plataforma cruzada (comunicar el código nativo de una aplicación -por ejemplo la provista en un activity de Android- con el Architect World -código JavaScript-) entre el código nativo y el código web: this.architectView.callJavascript( "newData('" +array.toString() + "');" );
function newData(jsonData){
jsonObject = JSON.parse(jsonData);
for(var i = 0; i < jsonObject.length; i++){
// use jsonObject[i] data to create the AR objects for each POI
}
}
- También podemos cargar los Puntos de Interés de un recurso local como un archivo aparte o alguna estructura de datos como un Array: var myJsonData = [{ "id": "1", "longitude": "13.0833", "latitude": "47.75", "description": "This is the description of POI#1", "altitude": "100.0", "name": "POI#1"}, {...}];
- O usando los Web Services siguiendo un formato como el siguiente: var ServerInformation = { // sample service returning dummy POIs POIDATA_SERVER: "http://example.wikitude.com/GetSamplePois/", POIDATA_SERVER_ARG_LAT: "lat", POIDATA_SERVER_ARG_LON: "lon", POIDATA_SERVER_ARG_NR_POIS: "nrPois" };
- Por supuesto podemos emplear cualquier otra tecnología como AJAX para obtener los Puntos de Interés o inclusive generar Puntos de Interés ficticios cercanos a la posición obtenida del dispositivo para casos de prueba; este último caso es el que emplearemos en nuestro experimento en la siguiente sección para obtener los Puntos de Interés.
Para más información, puedes consultar la documentación oficial RETRIEVING POI DATA
Desarrollando el código nativo (Java) de la aplicación
Ya aclarado ciertos conceptos claves sobre el funcionamiento de la plataforma cruzada en Wikitude para los Puntos de Interés, empecemos a obteniendo la localización del dispositivo.
Como se ha comentado a lo largo de esta entrada, el código nativo (Java) se encarga de obtener la posición del dispositivo mediante el GPS, red de telefonía, puntos de acceso Wi-Fi o alguna tecnología asociada; para poder obtener la ubicación del usuario debemos de tener solicitar los siguientes permisos en el AndroidManifest:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Una vez solicitados, podemos obtener la última ubicación válida el usuario mediante el método:
getLastKnownLocation(String provider)
Un punto importante es que Android no devuelve la posición actual del dispositivo si no la última registrada; en otras palabras el método llamado getLastKnownLocation(String provider)
no devuelve la posición actual, solo se limita a devolver la última posición que se obtuvo a través del proveedor que se le indique como parámetro y esta posición se pudo obtener hace segundos, minutos, horas, días, meses, etc.
Aunque es posible utilizar un "evento escuchador" que permite obtener la posición real del usuario actualizable según los valores de los parámetros suministrador mediante el método requestLocationUpdates()
que permite obtener la posición del usuario actualizada en el tiempo; dicho método recibe:
- Nombre del proveedor de localización.
- TIempo mínimo entre actualizaciones dadas en milisegundos.
- Distancia mínima entre actualizaciones dadas en metro.
- Instancia de un objeto LocationListener el cual definirá las acciones a realizar cuando se actualice la posición.
Definiendo el evento escuchador en nuestra activity
El siguiente fragmento de código será utilizado dentro de nuestra activity para actualizar la posición del usuario:
LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
if (location != NULL) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
architectView.setLocation(latitude, longitude, 1f);
}
//*** otras validaciones del evento escuchador
Una vez instanciado el "evento escuchador" indicamos que servicios de localización emplearemos; el GPS:
locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
Y la red de telefonía con los puntos de acceso Wi-Fi:
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
A la vez indicamos cada cuanto tiempo y distancia recorrida deseamos que se actualice la posición:
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 80000, 0,
locationListener);
Finalmente, devolvemos la posición:
Location location = locationManager .getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (location != NULL) { latitude = location.getLatitude(); longitude = location.getLongitude(); }
Lo versátil de esta tecnología es que podemos cargar sólo los Puntos de Interés cercanos a la posición del dispositivo en base a un rango; los Puntos de Interés se podrían ir actualizando conforme a la posición del dispositivo.
El resto del cuerpo de la activity es exactamente la misma utilizada en entradas anteriores sobre Wikitude; en cuanto al Architect World o código JavaScript es exactamente el mismo explicado en detalle en la parte uno de la entrada anterior.
Al ejecutar la aplicación podrás darte cuenta que pinta un simple POI:
Continuación del uso de los POI con Wikitude
En las siguientes entradas veremos como pintar múltiples Puntos de Interés e interactuar con los mismos; puedes descargar el código completo de la aplicación en nuestro repositorio de GitHub.
Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter