JavaFX location example with GPS

One of the cool things about the JavaFX Mobile platform running on my HTC Diamond phone, is the easy integration with GPS. In this article, I will describe the most simple example I could come up with.

I have been working with GPS integration in Java code since more than 10 years now. In most cases, I had to use the serial io provided in comm.jar implementations (the one providing javax.comm.SerialPort and others). Although this worked fine in most of the cases, the amount of low-level code was high compared with the amount of functional code.
I have been a big supporter of JSR 179, the Location API for J2ME. This API provides a simple way for obtaining locations and it also provides some common functionality (e.g. proximity listeners). Until recently, I haven't seen much devices that contained a clean implementation of this API. But this is changing.

The JavaFX Mobile 1.2 for Windows Mobile platform contains an implementation of JSR 179, and it works very well with JavaFX.
The following code example shows a simple JavaFX example showing the status of the built-in GPS and the latest known position. It probably violates some patterns, but the only goal is showing how you can obtain position in your JavaFX programs.

The main class

The main class is a typical JavaFX example containing a Stage with a Scene. The Scene contains 2 Text items. The contents of these text items are dynamically bound to some variables.
package com.lodgon.locationdemo;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;

public var gpsStatus: String = "unknown";
public var lat: Number = 0.0;
public var lon: Number = 0.0;

var stage: Stage = Stage {
    title: "Location demo"
    width: 250
    height: 120
    scene: Scene {
        content: [
            Text {
                font : Font { size : 16 }
                x: 10
                y: 30
                content: bind "gps status: {gpsStatus}"
            },
            Text {
                font : Font { size : 16 }
                x: 10
                y: 50
                content: bind "position: {lat}, {lon}"
            }
        ]
    }
}

function run () {
  stage;
  var processor: LocationProcessor = LocationProcessor{};
  processor.startReading();
}

No magic in here, notice the LocationProcessor class that we instantiate and that will do the interaction with the GPS. This instance will create a javax.microedition.location.LocationProvider and register a javax.microedition.location.LocationListener with it.

When the status of the GPS is changed, the providerStateChanged method is called. The new status is assigned to the gpsStatus variable in the Main class and shown on the device screen.
Similarly, when a new position is detected, the locationUpdate method is called, and the lat and lon variables in the Main class are changed.

package com.lodgon.locationdemo;
import javax.microedition.location.LocationListener;
import javax.microedition.location.Location;
import javax.microedition.location.LocationProvider;
import javax.microedition.location.QualifiedCoordinates;

public class LocationProcessor extends LocationListener  {

  var provider: LocationProvider;

  public function startReading() {
    provider = LocationProvider.getInstance(null);
    provider.setLocationListener(this, 10, 5, -1);
    providerStateChanged (provider, provider.getState());
  }

  override function locationUpdated(provider: LocationProvider, location: Location) {
    if (location != null) {
      var coords: QualifiedCoordinates = location.getQualifiedCoordinates();
      if (coords != null) {
        var lat = coords.getLatitude();
        var lon = coords.getLongitude();
        println ("[JVDBG] lat = {lat}");
        Main.lat = lat;
        Main.lon = lon;
      }
    }

  }

  override function providerStateChanged(provider: LocationProvider, stat: Integer) {
    if (stat == 1) {
      Main.gpsStatus = "Available";
    }
    if (stat == 2) {
      Main.gpsStatus = "Temporarily Unvailable";
    }
    if (stat == 3) {
      Main.gpsStatus = "Out Of Service";
    }
  }

}

For more information about JSR 179, see the Javadoc pages. You can easily change the update frequency (currently 10 seconds), timeout (currently 5 seconds), and other criteria. Also note that we actually should not do any processing in the interface callback methods. Since this is a simple example without much processing, I didn't use the javafx async threading mechanism for simplicity.

written on 26 Sep 2009 14:09.

no comments

Create comment