Leyendo nuestro GPS desde Java con la JavaME Location API (JSR-179) – Parte I
Introducción
La especificación JSR-179 Location API for J2ME pone a nuestra disposición una serie de clases que permiten acceder desde Java a información relacionada con la posición y el movimiento de nuestro dispositivo.
Lo que vamos a ver es una descripción básica de estas clases. Para probarlo necesitaremos un móvil que implemente al especificación JSR-179, como la mayoría de los Nokia o BlackBerry modernos.
Hay que tener en cuenta que no es necesario que el móvil disponga de GPS. La Location API nos aisla del origen de los datos, que puede ser un GPS o puede ser un servicio de pago proporcionado por la operadora. Debido a esto la API nos ofrece una serie de parámetros para filtrar qué tipo de servicios nos interesan de aquellos disponibles.
Fuentes de localización
En lo referente a localización, existen habitualmente tres fuentes posibles de datos:
- GPS: nuestro móvil incorpora un GPS, o está conectado a uno (habitualmente a través de Bluetooth).
- Assisted GPS: además de un GPS, nuestro móvil tiene acceso a información de localización que evita que el GPS pase hasta varios minutos obteniendo esa información de los satélites antes de dar la primera posición. Para ello es necesario un servicio específico ofrecido por algunas operadoras, habitualmente de pago.
- Cell Id: el móvil no tiene acceso a un GPS, pero sí a un servicio que le proporciona información basada en el identificador de la célula telefónica en la que se encuentra. También suele ser un servicio de pago por parte de las operadoras.
La Location API está preparada para el dispositivo tenga acceso a todo tipo de Location Providers o Proveedores de Localización, que es como se denominan a estas fuentes de datos. Para poder seleccionar entre las opciones actuales y futuras existe una clase que nos permite definir una serie de criterios que deba cumplir el proveedor que nos interese.
Estableciendo criterios
La clase javax.microedition.location.Criteria proporciona funciones que nos van a permitir filtrar los proveedores de localización disponibles. Veamos qué podemos definir en esta clase:
- La precisión horizontal y vertical.
Se establece mediante los métodossetHorizontalAccuracyysetVerticalAccuracy. La precisión de los datos depende de su origen. Así, si indicamos una precisión de 50 metros excluiremos los datos provenientes de localización por celda telefónica, que suelen tener precisiones de cientos de metros, pero aceptaremos los datos del GPS, con precisiones típicas de pocos metros. - El permiso para obtener datos a cambio de un precio.
Mediante el métodosetCostAllowed(false)(el valor por defecto es true) impedimos que nos cobren por obtener datos de localización. Esto excluye habitualmente el A-GPS y la localización por celda telefónica, que necesitan comunicación con la red telefónica para obtener la información, además de un posible sobrecoste por el servicio. - El nivel de consumo de batería.
A través del métodosetPreferredPowerConsumptionpodemos indicar si permitiremos un nivel de consumo bajo, medio o alto. Hay que tener en cuenta que es el fabricante del dispositivo quien decide qué es alto, medio o bajo, pero probablemente el uso de un dispositivo GPS interno o bluetooth tendrá un consumo medio o alto. - Otros criterios.
El tiempo de respuesta, la velocidad o información relativa a la dirección postal. Para una descripción más extensa, véase la referencia de la claseCriteria.
Accediendo al GPS
Una vez definidos los criterios, obtendremos una referencia al proveedor de contenidos. La clase LocationProvider implementa un método estático getInstance(Criteria criteria) que devuelve un proveedor que se adapte a los criterios que hemos indicado. Si ninguno de los proveedores disponibles encaja en los criterios indicados, el método devolverá null. En caso de que no exista ningún proveedor de localización disponible se lanzará una LocationException. Es posible llamar a getInstance pasando null como parámetro: de esta forma se especifican los parámetros menos restrictivos para la selección.
Utilizaremos la instancia obtenida de LocationProvider para obtener la posición mediante el método getLocation. En el podemos especificar un timeout, o tiempo que queremos que espere el sistema para obtener una posición. Una vez obtenida dispondremos de un objeto Location que contendrá, entre otras cosas, las coordenadas de nuestra ubicación.
Un ejemplo sencillo
Juntemos todo en un ejemplo muy sencillo, sólo útil para hacerse una idea del código descrito:
// Establecemos los criterios. Queremos sólo un GPS interno o Bluetooth
Criteria criteria = new Criteria();
criteria.setCostAllowed(false);
// Como el valor por defecto de los siguientes parámetros
// es NO_REQUIREMENT, las siguientes líneas no son necesarias
criteria.setHorizontalAccuracy(NO_REQUIREMENT);
criteria.setVerticalAccuracy(NO_REQUIREMENT);
criteria.setPreferredPowerConsumption(NO_REQUIREMENT);
// Aquí falta capturar la posible excepción y verificar que el
// valor devuelto no es null
LocationProvider lp = LocationProvider.getInstance(criteria);
// Con -1 indicamos el timeout por defecto
Location location = lp.getLocation(-1);
Coordinates coordinates = location.getQualifiedCoordinates();
System.out.println("Latitud: " + coordinates.getLatitude());
System.out.println("Longitud: " + coordinates.getLongitude());
Referencias:
Documentación on-line de la Location API

[...] información de la posición y velocidad obtenidas de un dispositivo GPS o similar (ver la entrada Leyendo nuestro GPS desde Java con la JavaME Location API (JSR-179) – Parte I para una explicación de las posibles fuentes de [...]
Bitácora móvil » Blog Archives » Leyendo nuestro GPS desde Java con la JavaME Location API (JSR-179) - Parte II
18 de enero de 2008 a 8:36
Hola Javier,
Soy un estudiante de Desarrollo de Aplicaciones Informaticas i estoy trabajando en un proyecto que usa J2ME y un GPS bluetooth, la cuestion es que me he mirado todos tus ejemplos, las API JSR-179, JSR-82 y aun asi no consigo conectar el al GPS i recibir datos.
Si me puedes orientar en algo tu ayuda sera muy bien recibida.
Muchas gracias,
att. Jaume.
Jaume
20 de mayo de 2008 a 16:34
Hola Jaume.
¿Podrías dar más datos? Dispositivo usado, qué código has probado y si da error o no hace nada,…
Javier Cancela
20 de mayo de 2008 a 17:04
Hola de nuevo Javier,
El deispositivo que estoy usando es un nokia n70 i un GPS bluetooth Royaltek RBT-1000
He definido los criterios e intento obtener el LocationProvider, pero no se si es que tengo que buscar los dispositivos con un DiscoveryAgent previamente o algo por el estilo.
En el emulador de sun el codigo funciona, pero en el movil parece que no arranque el midlet, es decir no me muestra ninguna pantalla ni de funcionamiento ni error, es como si no hiciera nada. El codigo es bastante similar al que tienes publicado arriba.
Estoy pensando en leer directamente del bluetooth i parsear los datos recibidos con algun paquete NMAE.
Espero que puedas ayudarme, sino gracias igualmente por prestarme atencion.
Jaume
21 de mayo de 2008 a 20:52
El problema con el N70 es que es un dispositivo S60 2nd Edition FP3, y no incorpora la Location API.
La solución que estás pensando es la correcta. Si miras este enlace: http://code.google.com/p/hipoqih/source/browse/trunk/hipoqihS60/src/com/hipoqih/plugin/s60_2nd/gps/?r=68 podrás ver un grupo de clases con licencia GLPL que utilicé yo para dispositivos con ese sistema (en concreto lo probé en un N70). La aplicación entera quedó sin depurar del todo pero la parte de acceso al GPS BT funciona bien. A ver si te sirve.
Javier Cancela
23 de mayo de 2008 a 7:37
Es justo lo que queria, con esto puedo seguir con mi proyecto, a ver si consigo que funcione todo.
Muchas gracias por toda tu ayuda.
Jaume
24 de mayo de 2008 a 20:41
Enhorabuena por los artículos, pues son de gran ayuda! Aunque mi BB 8800 se queda frito una vez le das a buscar la posición… El dispositivo te pide autorización para que la aplicación pueda acceder al GPS pero luego se queda ahí bloqueado y tengo que apagarlo (aunque haya especificado un timeout). Es posible que tenga que pedir a RIM un certificado?
Saludos!
Gerard
27 de mayo de 2008 a 12:18
Hola Gerard.
La Location API no pide certificado en BB, pero no está de más tenerlo porque es barato y hay APIs que lo necesitan.
Que se quede bloqueado y tengas que apagarlo se debe probablemente a que se está realizando una operación desde el thread de la interfaz de usuario, y esta operación está dando algún problema. En general cualquier operación potencialmente problemática, como una conexión a internet o a un GPS, debe realizarse desde un thread distinto.
De todos modos habría que ver en qué punto exacto se queda esperando para saber cuál es el problema.
Javier Cancela
27 de mayo de 2008 a 14:09
Muchas grácias por tus comentarios Javier.
Pues la verdad es que soy un poco “newbie” en el tema J2ME y aún tengo dudas. Aunque he intentado ejecutar un ejemplo de la misma web de BlackBerry:
Así defino la clase:
public class gpsTest extends MIDlet implements CommandListener, Runnable
y en el constructor ejecuto un nuevo hilo:
Thread t = new Thread(this);
t.start();
luego la obtención de las coordenadas la hago en el método run(). Creía que de esta forma me aseguraba de que no se quedaría bloqueado el BB.
Por cierto, esta es la página que he estado consultando:
http://na.blackberry.com/eng/developers/resources/journals/jan_2006/blackberry_gps.jsp#GPS_for_BlackBerry
Un saludo
Gerard
27 de mayo de 2008 a 14:32
¿Has probado a echar un vistazo a la aplicación GPSDemo de ejemplo de BlackBerry? La puedes encontrar aquí:
http://www.blackberry.com/knowledgecentersupport/kmsupport/supportknowledgebase/files/BlackBerry_Application_Developer_Guide_samples402.zip.
Hay varias entradas en este blog hablado de ese ejemplo, empezando por http://javiercancela.com/2008/01/09/un-ejemplo-de-aplicacion-java-para-blackberry-parte-i/
Otra cosa, si es una aplicación sólo para BlackBerry puede ser una buena idea utilizar la api de BB para la interfaz de usuario (net.rim.device.api.ui) en vez de usar un Midlet.
Javier Cancela
27 de mayo de 2008 a 20:50
He estado mirando la documentación de la API JSR179 y no encuentro la forma de averiguar la fecha y hora del GPS. Lo más parecido que he encontrado es la función getTimestamp de la clase Location pero especifica claramente que es el tiempo local en el que se adquirió la posición. ¿Cómo consigo la fecha y la hora que tiene el GPS?
Pablo
26 de junio de 2008 a 18:02
hola:
alguen me puede decir que telefonos implementan el api jsr 179, por que tengo un 6230i y me manda una exception indicando que no tiene el api location. gracias
pablois
29 de junio de 2008 a 18:55
Hola…soy nuevo en esto tambien y quiero realizar un proyecto web que utilice tegnologias de GPS y este foro creo que me ayudara bastante.
Comenzare de inmediato a probar esta clase para ver si me funciona, ya que es un proyecto que he tenido en mente hace como 3 años y no me habia decidido ha realizarlo, pero mas vale tarde que nunca.
Saludos…
Alexcom
17 de julio de 2008 a 22:03
Hola a todos, pues estoy empezando en esto de los GPS’s y no se mucho aun, hice el ejemplo que ponen mas arriba para obtener los datos de mi GPS(Royaltek BlueGPS 7C5862) lo corri en el emulador de Nokia serie S60, y me muestra la latitud y la longitud, pero veo que siempre me obtiene los mismo datos, este encendido mi dispositivo GPS o no, entonces no se si este leyendo realmente los datos de mi GPS o no? Podrian ayudarme a resolver esta duda??? Se los agradecere mucho y de ser necesario agregar algo mas para asegurarme de que realmente obtenga la informacion de mi GPS agradeceria tambien que lo mencionaran.. de antemano gracias.
moises
7 de septiembre de 2008 a 19:59
Javier
Buena tarde. Me pregunto si puedes echarme una mano en este problema: Estoy desarrollando para BlackBerry una aplicación que permita obtener datos del gps y los envíe a un servidor. Hasta aquí todo bien, sin embargo me he encontrado con las siguientes dificultades:
1. Hacer que el midlet se ejecute automáticamente sin intervención del propietario del equipo.
2. Hacer que cada cierto tiempo se ejecute automáticamente la aplicación.
3. En los simuladores funciona bien, pero al realizar pruebas en el equipo (BlackBerry 7520) éste parece bloquearse.
Dejo aquí el código que he implementado.
Saludos!!
***********************
public class GPS extends MIDlet implements CommandListener {
private Form myForm = null;
private Form lbsForm = null;
private Form wait = null;
private Form alert = null;
private Command getLocation = null;
private Command exit = null;
private Command back = null;
private Command cancel = null;
private Display display = null;
private GPS midlet = null;
public GPS(){
myForm = new Form(“GPS TEST”);
getLocation = new Command(“Location”,Command.OK,1);
exit = new Command(“Exit”,Command.EXIT,0);
myForm.addCommand(getLocation);
myForm.addCommand(exit);
myForm.setCommandListener(this);
midlet = this;
}
public void startApp() {
display = Display.getDisplay(this);
display.setCurrent(myForm);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command aCommand, Displayable aDisplayable) {
if( aCommand.getCommandType() == Command.EXIT ){
notifyDestroyed();
}
if( aCommand.getCommandType() == Command.BACK ){
display.setCurrent(myForm);
}
if( aCommand.getLabel().equals(“Location”) ){
new Thread(){
public void run(){
try{
HttpConnection httpConn = null;
StreamConnection s = null;
InputStream in = null;
wait = new Form(“Wait please”);
wait.append(“Conecting…\n”);
cancel = new Command(“Cancel”,Command.CANCEL,0);
wait.addCommand(cancel);
wait.setCommandListener(midlet);
display.setCurrent(wait);
LocationProvider theLocationProvider = LocationProvider.getInstance(null);
wait.append(“Obtengo Proveedor\n”);
Thread.sleep(2);
wait.append(“Se detiene la aplicación\n”);
//QualifiedCoordinates theQualifiedCoordinates = getCoordinates();
wait.append(“Se establecen los criterios del proveedor\n”);
Criteria theCriteria = new Criteria();
theCriteria.setHorizontalAccuracy(1000);
theCriteria.setPreferredPowerConsumption(theCriteria.POWER_USAGE_LOW);
QualifiedCoordinates theQualifiedCoordinates = null;
//theLocationProvider = LocationProvider.getInstance(theCriteria);
theLocationProvider = LocationProvider.getInstance(null);
wait.append(“Se localiza al proveedor\n”);
Location theLocation = theLocationProvider.getLocation(60);
wait.append(“Obtengo la Ubicación\n”);
theQualifiedCoordinates = theLocation.getQualifiedCoordinates();
wait.append(“Ubicaciones: “+theQualifiedCoordinates.getLatitude()+” “+theQualifiedCoordinates.getLongitude()+”\n”);
lbsForm = new Form(“Location Form”);
if( theQualifiedCoordinates == null ){
wait.append(“Error reciveing coordinates!”);
display.setCurrent(lbsForm);
}
else{
lbsForm.append(“Alt: “+theQualifiedCoordinates.getAltitude()+”\n”);
lbsForm.append(“Lat: “+theQualifiedCoordinates.getLatitude()+”\n”);
lbsForm.append(“Long: “+theQualifiedCoordinates.getLongitude());
display.setCurrent(lbsForm);
Thread.sleep(3);
s = (StreamConnection) Connector.open(“http://Aqui pongo la dirección de mi svr…?Longitud=”+theQualifiedCoordinates.getLongitude()+”&Latitud=”+theQualifiedCoordinates.getLatitude()+”;deviceside=true”);
httpConn = (HttpConnection) s;
int status = httpConn.getResponseCode();
wait = new Form(“Conecting to URL: “);
wait.append(“Conecting…\n”/*+completeURL*/);
wait.addCommand(exit);
wait.setCommandListener(midlet);
display.setCurrent(wait);
if (status == HttpConnection.HTTP_OK) {
httpConn.close();
}
//Thread.sleep(2);*/
wait = new Form(“Se conecto”);
wait.append(“Nueva conexión \n”);
wait.addCommand(exit);
wait.setCommandListener(midlet);
display.setCurrent(wait);
}
}
catch (InterruptedException e) {
alert = new Form(“Error”);
alert.append(“Interrupted Exception \n”+e.getMessage());
alert.addCommand(back);
alert.setCommandListener(midlet);
display.setCurrent(alert);
}
catch(NullPointerException ex){
alert = new Form(“Error”);
alert.append(“Null pointer! \n”+ex.getMessage());
alert.addCommand(back);
alert.setCommandListener(midlet);
display.setCurrent(alert);
} catch (LocationException e) {
alert = new Form(“Error”);
alert.append(“Location Exception \n”+e.getMessage());
alert.addCommand(back);
alert.setCommandListener(midlet);
display.setCurrent(alert);
}
catch(Exception ex){
alert = new Form(“Error”);
alert.append(“An exception \n”+ex.getMessage());
alert.addCommand(back);
alert.setCommandListener(midlet);
display.setCurrent(alert);
}
}
}.start();
}
if( aCommand.getCommandType() == Command.CANCEL ){
display.setCurrent(myForm);
}
}
}
***************************************
Carlos
23 de septiembre de 2008 a 19:02
A simple vista, el principal problema está en el código que muestra los Forms:
wait = new Form(”Conecting to URL: “);
wait.append(”Conecting…\n”/*+completeURL*/);
wait.addCommand(exit);
wait.setCommandListener(midlet);
display.setCurrent(wait);
Para no bloquear el thread de la interfaz de usuario (la UI sólo puede ser accedida por un thread a la vez) pon ese código en cola:
UIApplication.invokeLater(new Runnable()
{
public void run()
{
//código
}
});
En vez de un MIDlet, usa las clases propias de BB: UiApplication en net.rim.device.api.ui.
Javier Cancela
24 de septiembre de 2008 a 21:29
Javier
Hola nuevamete. Gracias por la ayuda, en efecto, había errores con el código de los forms.
Esa parte ya la he solucionado, pero ahora me he atorado en algo que de lo que tengo idea. Me pregunto si conoceras algo al respecto.
1. Es posible hacer que una aplicación se autoejecute en la BB una vez instalada?
2. Es posible que esa aplición se ejecute en segundo plano?
3. Como hago para no utilizar la interface de usuario? Quiero enviar los datos que me da el GPS directamente aun SVR. El proceso ya lo hace, pero ahora quiero eliminar la intervención del usuario. Es decir, que no haya que desencadenar los eventos a travez de los CommandListening
Puedes hacerme algunos comentarios al respecto?
Desde ya gracias!!
Carlos
29 de septiembre de 2008 a 19:27
Hola Javier.
Primero que todo permitame felicitarlo por los apuntes que nos has dejado, son muy concretos y faciles de dijerir.
Bueno, en este momento necesito hacer un desarrollo con GPS, he probado el ejemplo que pones aqui y no me genera error de ningun tipo, ni al compilar ni al ejecutar; sin embargo, cuando lo ejecuto siempre las coordenadas que me arroja son 0,0.
Cabe anotar que lo estoy probando en un emulador (NetBeans 6), se me ocurre que es por esto y soy optimista al creer que si lo monto en un dispositivo real funcionara correctamente, es asi?
Por otra parte, me pregunto que dispositivo deberia tener para que funcione correctamente el ejemplo (que tipo de caracteristicas, especificaciones y demas), ademas para que pueda poner en este mismo dispositivo un desarrollo Java – J2ME – CDC.
Finalmente y despues de haber expuesto mis problematicas, me preguntaba si de algun modo me puede colaborar. De verdad que lo necesito de caracter urgente.
De momento no es mas, sin mas presentes y quedando infinitamente agradecido por la atencion y colaboracion prestada, me despido quedando en espera de una respuesta.
Hasta pronto y exitos.
Posdata: Cuando este ejemplo me arroja las coordenadas, son coordenadas GPS? es decir, arroja valores bajo que punto de referencia?
Saludos y de nuevo gracias.
Pavel Franco Marin
12 de octubre de 2008 a 16:32
Hola a todos
Tengo un proyecto de aficionado, pero no tengo ni idea de java o pearl o lo que sea esto, lo que quiero es programa que capture la posicion la envie por correo y yo desde la oficina poder localizar la bb, en visual access os podria ayudar pero ahora estoy bastante pez
carlos
23 de octubre de 2008 a 7:54
Hola de nuevo.
Este blog es de lo mejorcito que he encontrado en base a estas tecnologías…
A ver si me podéis ayudar, sabéis la manera para poder acceder a la información: CELL-ID, MCC, MNC, LOC,etc?
Todo es mediante System.getProperty(“…”);
Pero siempre me devuelve “null”.
Estoy probando con un N95.
Saludos y gracias!
Pablo
25 de noviembre de 2008 a 13:30
Hola a todos
Soy nuevo en toda esta tecnologia me gustaria que me colaboren, quiero hcer mi trabajo de grado y el problema es el siguiente
necesito adquirir la posicion y velocidad de una flota de vehiculos y llevar esta informacion a una base de datos central para despues ser analizados estos datos mi correo es frealpe@gmail.com les agradeceria que me dijeran que dispositivo GPS barato debo utilizar y si debo instalar una red
Gracias
Fabio
6 de febrero de 2009 a 22:56
Lo primero darte las gracias por toda esta informacion. Sin esto no sabria por donde empezar!! Gracias!!!
Ahora tengo una duda/problema.
Con tu codigo me salta una exception en Location location = lp.getLocation(-1); y no tengo ni idea como arreglarlo.. me da a mi que me tendra que faltar algo.
Espero que me puedas ayudar!
Gracias por todo!
Paquito
10 de febrero de 2009 a 10:28
Hola,
Para quien preguntaba como ejecutar periódicamente un código J2ME, míra la especificación Push Registry, en concreto la parte de alarmas, dado que puedes programar que cada cierto tiempo se ejecute un MIDLet.
También usando esta API puedes hacer que un teléfono al recibir un Push SMS se ejecute un MIDLet.
Espero haberte asesorado al respecto.
Un saludo, Oscar.
Oscar
10 de febrero de 2009 a 16:20
Hola, Excelente el tutorial!!!
Estoy probando el código con algunos cambios y si bien en el emulador de Netbeans 6.5 funciona perfecto cuando lo instalo en un teléfono Nokia para poder probar me dice aplicación no valida, ¿que puede estar sucediendo?
Gracias y Saludos
Maxi
Maximiliano Bacci
13 de marzo de 2009 a 16:31
hola a todos,
alguien podria ayudarme para ejecutar una aplicacion de localizacion GPS usando netbenans o el emulador wirelss tolkit CLDC, no c como simular datos GPS.
Gracias
Hawer
24 de marzo de 2009 a 16:46
Hola, queria saber si alguien sabe como ejecutar una aplicacion hecha en java j2me para blackberry en segundo plano??? Gracias!
Fito
2 de julio de 2009 a 14:23
Hola a todos,
Estoy intentando obtener datos del GPS por medio de JavaME, estoy probando las aplicaciones en un HP iPAQ 610, pero no puedo conectarme al GPS,
Alguna ayuda……?
Matby Peralta
18 de agosto de 2009 a 17:06
hola
necesito localizar cualquier cell para brindarle un servicio determinado q el usuario solicite mediante un mapa, mi gran problema es q no se como puedo capturar el cell id en j2me ya q no puedo hacerlo por gps o por otra via, usted me puede ayudar, facilitarme el fragmento del codigo o el algoritmo q hay q seguir???
armando
23 de octubre de 2009 a 15:01
Saludos, he estado creando una aplicacion de localización GSM, pero sólo funciona en equipos nokia serie N-XX , cómo podría hacer para que funcione en equipos Nokia 5130, 5310 o inferiores que no tienen el api jsr 179?. Pues la idea es que las personas no tengan que invertir en equipos tan costosos.
Gracias, felicitaciones es el mejor sitio que he encontrado que habla de este tema
adrian izquierdo
24 de noviembre de 2009 a 15:58