I just started coding in J2ME just under a year ago, when I wanted to build a GPS Golf application. After learning the wrong way to do it, I found a GPS class that I have changed a bit to suit my needs. The following is a simple GPS class that will run on its own thread in the background, and you can use the get methods to get any of the GPS data that is avaliable. The way I use the Class is with a Timer Task, but I’m sure it could be changed to use a lister if that is what you are looking. Remember It’s code, you can do anything!
Here is my GPS class that I use:
import javax.microedition.location.Location;
import javax.microedition.location.LocationException;
import javax.microedition.location.LocationListener;
import javax.microedition.location.LocationProvider;
import javax.microedition.location.QualifiedCoordinates;
/**
*
* @author Justin
*
*/
public class GPS extends Thread {
private double latitude;
private double longitude;
private String satCountStr;
private float accuracy;
private double heading;
private double altitude;
private double speed;
private int interval = 1; // time in seconds to get new gps data
/**
* This will start the GPS
*/
public GPS() {
// Start getting GPS data
if (currentLocation()) {
// This is going to start to try and get me some data!
}
}
private boolean currentLocation() {
boolean retval = true;
try {
LocationProvider lp = LocationProvider.getInstance(null);
if (lp != null) {
lp.setLocationListener(new LocationListenerImpl(), interval, 1, 1);
} else {
// GPS is not supported, that sucks!
// Here you may want to use UiApplication.getUiApplication() and post a Dialog box saying that it does not work
retval = false;
}
} catch (LocationException e) {
System.out.println("Error: " + e.toString());
}
return retval;
}
private class LocationListenerImpl implements LocationListener {
public void locationUpdated(LocationProvider provider, Location location) {
if (location.isValid()) {
heading = location.getCourse();
longitude = location.getQualifiedCoordinates().getLongitude();
latitude = location.getQualifiedCoordinates().getLatitude();
altitude = location.getQualifiedCoordinates().getAltitude();
speed = location.getSpeed();
// This is to get the Number of Satellites
String NMEA_MIME = "application/X-jsr179-location-nmea";
satCountStr = location.getExtraInfo("satellites");
if (satCountStr == null) {
satCountStr = location.getExtraInfo(NMEA_MIME);
}
// this is to get the accuracy of the GPS Cords
QualifiedCoordinates qc = location.getQualifiedCoordinates();
accuracy = qc.getHorizontalAccuracy();
}
}
public void providerStateChanged(LocationProvider provider, int newState) {
// no-op
}
}
/**
* Returns the terminal's course made good in degrees relative to true north.
* The value is always in the range (0.0,360.0) degrees.
*
* @return double
*/
public double getHeading() {
return heading;
}
/**
* Returns the altitude component of this coordinate.
* Altitude is defined to mean height above the WGS84 reference ellipsoid.
* 0.0 means a location at the ellipsoid surface, negative values mean the
* location is below the ellipsoid surface, Float.NaN that no altitude is
* available.
*
* @return double
*/
public double getAltitude() {
return altitude;
}
/**
* Get the number of satellites that you are currently connected to
*
* @return String
*/
public String getSatCount() {
return satCountStr;
}
/**
* Get the Accuracy of your current GPS location
*
* @return float
*/
public float getAccuracy() {
return accuracy;
}
/**
* Returns the latitude component of this coordinate.
*
* Positive values indicate northern latitude and negative values southern latitude.
*
* @return double
*/
public double getLatitude() {
return latitude;
}
/**
* Returns the longitude component of this coordinate.
*
* Positive values indicate eastern longitude and negative values western longitude.
*
* @return double
*/
public double getLongitude() {
return longitude;
}
/**
* Get your current ground speed in meters per second (m/s) at the time of measurement
*
* @return double
*/
public double getSpeed() {
return speed;
}
}
Once you have added the GPS class to your project you can then use it the following way:
GPS gps = new GPS(); gps.start();
I like to start my GPS class as soon as my application starts up because it can take anywhere between 2 to 10 minutes for the BlackBerry to get a GPS lock. It will depend where they are. If you are outside with a clear view of the sky it works best (line of sight). Once you have the GPS option you can just pass the object between your screens or, if you want or you can just start a new GPS object, and if the first GPS object already has a lock then the new GPS class will get a lock right away.
Like I said before I like to use a Timer Task to update my screen UI. The reason for this is that it give me more options. This way I can tell the applciation how often I want to update the screen with the new data. I do it the following way:
import java.util.Timer;
import java.util.TimerTask;
import net.rim.device.api.ui.component.RichTextField;
import net.rim.device.api.ui.container.MainScreen;
public class GPSScreen extends MainScreen {
GPS gps;
Timer timer;
RichTextField txtGPS;
public GPSScreen(){
gps = new GPS();
timer = new Timer();
timer.schedule(new CheckGPS(), 100, 1000); //check for GPS every 1 second;
String textGPS = "";
txtGPS = new RichTextField(textGPS, RichTextField.NON_FOCUSABLE);
add(txtGPS);
}
public boolean onClose()
{
timer.cancel(); //cleanup
this.close();
return true;
}
public class CheckGPS extends TimerTask{
public CheckGPS() {
}
public void run() {
double lat;
double lng;
lat = 0;
lng = 0;
lat = gps.getLatitude();
lng = gps.getLongitude();
if (lat != 0.0 & lng != 0.0) {
synchronized (MyApplicationName.getEventLock()) {
double acc = gps.getAccuracy();
txtGPS.setText(lat + ", " + lng + " (" + gps.getSatCount() + ") (" + (int) acc + ")");
}
}
else
{
String thetxt = txtGPS.getText();
synchronized (MyApplicationName.getEventLock()) {
if(thetxt.length() > 10)
if(thetxt.length() > 25)
txtGPS.setText("Waiting for GPS.");
else
txtGPS.setText(thetxt + ".");
else
txtGPS.setText("Waiting for GPS.");
}
}
}
}
}
Here is a screen shot from my simulator:

GPSScreen in use with the GPS class
So within my Timer Task that runs once every second I use my get methods to get the Lat and the Long from GPS and I check to see if they are set. You could also add some more logic into the GPS class with a boolean flag to see if we have a GPS lock before you even get the values.
This GPS class will work with (almost) any BlackBerry Smartphone device that is GPS enabled. It will not work for Verizon 8130, 8330, and 8830, but it does work with the Verizon Storm and Tour. This Class will work with any 4.2 device that has a Bluetooth GPS receiver, including the Verizon devices listed above (8130, 8330, and 8830) as a workaround to the Verizon GPS lock-down.
Here is some related GPS information:
Enjoy!
Justin






5 Responses
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.
In some implementations GPS may pass null location in LocationListenerImpl.locationUpdate method.
I have had a lot of problems with my 8800 until I detected this behaviour
This is not reproduced on the simulator.
Great post! Good to see a full GPS code listing, with supporting comments. Shame the bberry devices take 2+ minutes to obtain a lat/lon. Makes it almost unusable in today’s “i want it now” environment. User just won’t wait that long, especially when the see an iPhone return the lat/lon on demand. RIM has made some good decisions along the way, but they definitely have failed in some others. Thanks for the post, good read.
Nice code Justin, thanks for sharing! Out of curiosity, is it alright to use this code, or a derivative of it, in a commercial project?
Either way, nice code!
thank you Justin…
Continuing the Discussion