viernes, 18 de febrero de 2011

TUTORIAL: Desarrollo de aplicaciones para bada (XIX)

Obtener ubicación por GPS y mostrarla en un mapa

En este post se muestra el proceso para desarrollar una aplicación que sea capaz de obtener información geográfica, mostrarla en forma de mapa en un dispositivo bada, y que además muestre la posición actual del usuario en el mapa.

Usaremos el namespace Osp::Locations, que contiene, entre otras, las clases LocationProvider y Location, que utilizaremos en este ejemplo. Con la clase LocationProvider se define de dónde se quiere obtener nuestra posición (por ejemplo, del GPS). Esta clase implementa la interfaz ILocationListener, que ofrece información acerca de actualizaciones de ubicación. La clase Location, que representa la información de la ubicación, es una parte de LocationProvider.
Además, el namespace Osp::Locations ofrece una serie de servicios útiles que pueden ser aprovechados por el desarrollador. Un servicio esencial que vamos a ver es el que se encapsula en la interfaz  IMapServiceProvider.

También usaremos el namespace Osp::Locations::Controls, que permite a los usuarios desplazarse, hacer zoom e interactuar con los mapas.

Para poder mostrar mapas en nuestra aplicación, es necesario tener acceso a un proveedor de datos geográficos. En este ejemplo usamos deCarta como proveedor de mapas. Puedes registrarte en deCarta y solicitar una clave (key) de forma gratuita.
Para solicitar una clave para una aplicación, en la misma web donde te registraste, accede con tus credenciales, dirígete a "My Account", haz clic en "Applications" y luego en el botón "Create a New Application". Introduce los datos de la aplicación y haz clic en "Register Application":


Se generará una clave (key) para tu aplicación, que podrás ver en "My Applications" (de todos modos te enviarán un correo electrónico con todos los datos necesarios para tu aplicación):


Bien, veamos ahora los puntos clave de la aplicación (hay un enlace al código completo al final del post) , en concreto el código de las siguientes clases:

- MapVisualisation.cpp (cubre el código para la representación de datos geográficos en un mapa)
- MapInteraction.cpp (cubre el código para la obtención de lugares)

Primero vamos a vincular nuestra cuenta de deCarta en la aplicación mediante la creación de un objeto Map Provider. Esto lo hacemos en la clase MapVisualisation. Sustituye XXX / YYY por tu "client name" y tu "key", respectivamente:

// Especificar el nombre del proveedor 
String providerName = L"deCarta"; 
// Especificar la clave proporcionada por el proveedor (sustituye XXX/YYY por tu usuario/contraseña[key]) 
static const String extraInfo = L"ClientName=XXX;ClientPassword=YYY;" "HostUrl=http://bada.developer.decarta.com/openls/openls"; 
// Crea un proveedor de mapas 
IMapServiceProvider* pProvider = static_cast
( ProviderManager::ConnectToServiceProviderN(
L"deCarta", LOC_SVC_PROVIDER_TYPE_MAP, extraInfo));

Después, construye un control de tipo Map y configúralo de acuerdo a tus necesidades:

// Crear control de tipo Map
Map* pMap = new Map(); 
// Construir el mapa 
pMap->Construct(Osp::Graphics::Rectangle(0, 0, GetCanvasN()->GetBounds().width, GetCanvasN()->GetBounds().height), *pProvider); 
// Configuracion:
pMap->SetPanEnabled(true); 
// Configuracion: definir el centro del mapa 
// Ej.: coordenadas de Staines, Reino Unido
double lat = 51.433315; double lon = -0.497382;
pMap->SetCenter(lat, lon, false); 
// Configuracion: mostrar mi ubicacion
pMap->SetMyLocationEnabled(true);

Es importante especificar la propiedad que define el área de mapa seleccionada. Su valor por defecto es "global-mobile". El resto de códigos de área se pueden encontrar en la web de deCarta. En este ejemplo vamos a utilizar el código "global-mobile" para acceder a los datos del mapa global. Esto se hace mediante la invocación de SetPreferencePropertyValue(), un método miembro de la clase Map. Se pueden obtener más opciones de configuración del mapa en la web de desarrolladores de deCarta.

// Establecer valores de configuracion de area seleccionada
static const String CONFIGURATION_VALUE(L"global-mobile"); 
pMap->SetPreferencePropertyValue(String(L"configuration"), &CONFIGURATION_VALUE);

Ahora vayamos a la clase MapInteraction. Crea y construye un LocationProvider especificando tu mecanismo de localización. Nosotros utilizaremos el receptor GPS. También puedes configurar la frecuencia de actualización. Establécela en 5 segundos en el método RequestLocationUpdate():

// Create a LocationProvider 
LocationProvider *locProvider = new LocationProvider(); 
// Construct the LocationProvider by using GPS as its locating mechanism 
locProvider->Construct(LOC_METHOD_GPS); 
// Configure the time interval for updates locProvider->RequestLocationUpdates(*this, 5, false);

Para recibir actualizaciones de ubicación, sobreescribe el método OnLocationUpdated()declarado en la interfaz ILocationListener:

//Invocado cuando se recibe un evento de tipo ubicacion 
void MapInteraction::OnLocationUpdated(Location& location)
   if(location.GetQualifiedCoordinates()!=null) 
   { 
      const QualifiedCoordinates *q = location.GetQualifiedCoordinates(); 
      // Latitud y longitud 
      double longitude = q->GetLongitude(); 
      double latitude = q->GetLatitude(); 
      // Centrar el map en torno a estos nuevos valores  
      pFormMap->SetCenter(latitude, longitude, true); 
      // Redibujar y mostrar el mapa 
      pFormMap->Draw(); 
      pFormMap->Show(); 
   } 
}

Una vez que el código se compile sin errores se puede ejecutar la aplicación en el emulador. Una herramienta muy útil del emulador es el inyector de eventos (event injector). Para acceder a él, haz clic derecho en la pantalla del emulador, selecciona "Event Injector", y elege la pestaña "Location". Puedes arrastrar y colocar el puntero en el mapa, o introducir directamente los valores de latitud y longitud. Estos son enviados como eventos a la aplicación. Es una herramienta muy útil para hacer pruebas.

Si no se muestra ningún mapa en la pantalla del emulador (*), probablemente lo primero que debes comprobar es si el nombre de usuario y contraseña que te proporcionó tu proveedor de datos geográficos son correctos. Otra razón podría ser que te conectes a Internet a través de un proxy. En ese caso especifica el proxy en el emulador (Menú > Ajustes > Conectividad > Red > Conexiones > bada).

Uso en BuddyFix

Puedes utilizar este ejemplo en la aplicación BuddyFix para mostrar en un mapa la posición actual de los contactos.



* NOTA IMPORTANTE: He probado a ejecutar la aplicación en el emulador y en el móvil varias veces con los datos correctos y sin proxy, y ninguna vez aparece el mapa, debido a un error de autenticación (¿?):




He realizado diferentes pruebas pero no he logrado solucionar el error. Si alguien sabe a que puede ser debido el error, por favor que deje un comentario.


No hay comentarios:

Publicar un comentario