Vames a ver ahora una descripción de la aplicación GPSDemo, que viene de ejemplo con la versión 4.1 del JDE de BlackBerry. Esta aplicación nos permite leer el GPS de nuestro dispositivo para mostrar en pantalla información sobre nuestra posición y velocidad, además de grabar durante nuestro recorrido una serie de waypoints que contienen la distancia recorrida, el tiempo y la velocidad media.

La aplicación GPSDemo consta de varias clases, agrupadas en dos archivos: GPSDemo.java y PointScreen.java. Comenzaremos por el archivo principal.

GPSDemo.java

La clase hereda de nuestra clase base BaseApp, e implementa la interfaz de los recursos (de la que ya hablamos en la entrada anterior):

public class GPSDemo extends BaseApp implements GPSDemoResResource<br /> {

// Constants. —————————————————————-

// The number of updates in seconds over which the altitude is calculated.

private static final int GRADE_INTERVAL=5;

// com.rim.samples.docs.gpsdemo.GPSDemo.ID

private static final long ID = 0x4e94d9bc9c54fed3L;

private static final int CAPTURE_INTERVAL=10;

// Statics. ——————————————————————

private static ResourceBundle _resources =

ResourceBundle.getBundle(GPSDemoResResource.BUNDLE_ID, GPSDemoResResource.BUNDLE_NAME);

// The period of the position query in seconds.

private static int _interval = 1;

private static Vector _previousPoints;

private static float[] _altitudes;

private static float[] _horizontalDistances;

Obtenemos una referencia a los recursos e inicializamos varias variables que usaremos posteriormente. A continuación comprobamos si tenemos datos almacenados en el dispositivo:

private static PersistentObject _store;<br /> // Initialize or reload the persistent store.<br /> static<br /> {<br /> _store = PersistentStore.getPersistentObject(ID);<br /> if(_store.getContents()==null)<br /> {<br /> _previousPoints= new Vector();<br /> _store.setContents(_previousPoints);<br /> }<br /> _previousPoints=(Vector)_store.getContents();<br /> }

El objeto PersistentStore nos permite persistir información en la BlackBerry a través de pares clave-valor; en este caso utilizamos como clave un ID definido por nostros. Usar este objeto nos obliga a firmar la aplicación para poder instalarla en el dispositivo. De la firma de aplicaciones BlackBerry hablaremos en el futuro.

Método main y constructor

private long _startTime;<br /> private float _wayHorizontalDistance;<br /> private float _horizontalDistance;<br /> private float _verticalDistance;<br /> private ListField _listField;<br /> private EditField _status;<br /> private StringBuffer _messageString;<br /> private String _oldmessageString;<br /> private LocationProvider _locationProvider;

`/* Instantiate the new application object and enter the event loop.

  • @param args unsupported. no args are supported for this application
    */
    public static void main(String[] args)
    {
    new GPSDemo().enterEventDispatcher();
    }`

La aplicación se inicia en el método estático main, que sólo crea una instancia de GPSDemo y pone el thread a la espera de eventos mediante la llamada al método enterEventDispatcher()(que se hereda de BaseApp, quien lo hereda de UiApplication y este a su vez de Application, la clase base de las aplicaciones BlackBerry). Vayamos ahora con el constructor:

// Constructor<br /> public GPSDemo()<br /> {<br /> // Used by waypoints; represents the time since the last waypoint.<br /> _startTime = System.currentTimeMillis();<br /> _altitudes=new float[GRADE_INTERVAL];<br /> _horizontalDistances=new float[GRADE_INTERVAL];<br /> _messageString= new StringBuffer();<br /> MainScreen screen = new MainScreen();<br /> screen.setTitle(new LabelField(_resources.getString(GPSDEMO_TITLE), LabelField.USE_ALL_WIDTH));<br /> _status = new EditField();<br /> screen.add(_status);<br /> screen.addKeyListener(this);<br /> screen.addTrackwheelListener(this);<br /> // Start the GPS thread that listens for updates.<br /> startLocationUpdate();<br /> // Render our screen.<br /> pushScreen(screen);<br /> }

Se inicializan variables de instancia y se crea la pantalla principal, a la que añadimos un EditField, que es un campo de texto editable (si no decimos lo contrario en el constructor). Mediante las llamadas a screen.addKeyListener(this) y screen.addTrackwheelListener(this) le decimos a la pantalla que nosotros (GPSDemo) gestionaremos sus eventos de teclado y trackwheel, lo cual podemos hacer porque nuestra clase base BaseApp implementa las interfaces KeyListener y TrackwheelListener.

Finalmente, añadimos la pantalla a la pila de pantallas. La gestión de ventanas la realiza la clase UIApplication como una pila: cuando necesitamos una ventana la metemos en la pila (pushScreen) y cuando acabamos con ella la sacamos (popScreen). El método pushScreen provoca que se pinte la pantalla, así que es importante llamarlo al final, cuando la ventana ya está totalmente construida.

Podemos ver también en el constructor una llamada a startLocationUpdate(), pero dejaremos esa parte para más adelante.

El menú

Nuestra clase base implementaba una versión básica del método makeMenu(Menu menu, int instance). Sin embargo, nosotros vamos a sustituir (override) esta versión con nuestra propia implementación:

// Menu items.<br /> // Cache the markwaypoint menu item for reuse.<br /> private MenuItem _markWayPoint = new MenuItem(_resources, GPSDEMO_MENUITEM_MARKWAYPOINT, 110, 10)<br /> {<br /> public void run()<br /> {<br /> GPSDemo.this.markPoint();<br /> }<br /> };

<br /> // Cache the view waypoints menu item for reuse.<br /> private MenuItem _viewWayPoints = new MenuItem(_resources, GPSDEMO_MENUITEM_VIEWWAYPOINTS, 110, 10)<br /> {<br /> public void run()<br /> {<br /> GPSDemo.this.viewPreviousPoints();<br /> }<br /> };

// Cache the close menu item for reuse.<br /> private MenuItem _close = new MenuItem(_resources, GPSDEMO_MENUITEM_CLOSE, 110, 10)<br /> {<br /> public void run()<br /> {<br /> System.exit(0);<br /> }<br /> };

protected void makeMenu(Menu menu, int instance)<br /> {<br /> menu.add( _markWayPoint );<br /> menu.add( _viewWayPoints );<br /> menu.add( _close );<br /> menu.addSeparator();<br /> super.makeMenu(menu, instance);<br /> }

Aparte de mostrar en la pantalla principal información de nuestra posición y velocidad, como veremos más adelante, GPSDemo nos permite crear y gestionar waypoints, puntos donde se almacena información sobre la distancia, el tiempo y la velocidad entre una posición y la anterior. Para ello añadimos una opción en el menú que nos permita marcar un waypoint y otra que nos permita acceder a la ventana de gestión de waypoints. Finalmente añadimos un separador y la opción de salir de la aplicación. Se llama después al método de la clase padre, que tenía el código que añadía menús contextuales en caso de hacer click en un control.

Marcar un waypoint

El método al que llama la opción de marcar un waypoint es el siguiente:

`/* Marks a point in the persistent store. Calculations are based on

  • all data collected since the previous way point, or from the start
  • of the application if no previous waypoints exist.
    */
    private void markPoint()
    {
    long current = System.currentTimeMillis();
    WayPoint p= new WayPoint(_startTime, current, _wayHorizontalDistance, _verticalDistance);
    addWayPoint(p);
    // Reset the waypoint variables.
    _startTime = current;
    _wayHorizontalDistance = 0;
    _verticalDistance = 0;
    }`

Se crea un objeto WayPoint con la hora en la que se grabó el waypoint anterior, la hora actual, y las distancias horizontal y vertical recorridas. La información de la distancia la establece el código que lee el GPS, que veremos más adelante. La clase WayPoint se define dentro de la propia clase GPSDemo:

`/* WayPoint describes a way point, a marker on a journey or point of interest.

  • WayPoints are persistable.
  • package
    */
    static class WayPoint implements Persistable
    {
    public long _startTime;
    public long _endTime;
    public float _distance;
    public float _verticalDistance;`

<br /> public WayPoint(long startTime,long endTime,float distance,float verticalDistance)<br /> {<br /> _startTime=startTime;<br /> _endTime=endTime;<br /> _distance=distance;<br /> _verticalDistance=verticalDistance;<br /> }<br /> }

El wayPoint se añade al vector se declaró al principio de la clase y que se almacena en la flash de la BlackBerry:

`/* Adds a new WayPoint and commits the set of saved waypoints

  • to flash memory.
  • @param p The point to add.
    /
    /
    package*/
    synchronized static void addWayPoint(WayPoint p)
    {
    _previousPoints.addElement(p);
    commit();
    }
    // Commit the waypoint set to flash memory.
    private static void commit()
    {
    _store.setContents(_previousPoints);
    _store.commit();
    }`

En la siguiente entrada hablaremos de la gestión de los waypoints y de la clase PointScreen.

Entradas relacionadas:

Un ejemplo de aplicación Java para BlackBerry – Parte I

Un ejemplo de aplicación Java para BlackBerry – Parte II