The Location Application BLACKBERRY

Now let’s put all this knowledge to use and create an application that uses the location API. aAs you should expect by now, you’ll start by creating a new BlackBerry CLDC application. Call it Location. Create a main application class and a main screen class called LocationApp and LocationMainScreen, respectively; both are in the com.beginningblackberry.location package. You’ll add a few fields to LocationMainScreen, a menu item to update the location, and a skeleton update method. The initial versions of the classes are as follows:

package com.beginningblackberry.location;
import net.rim.device.api.ui.UiApplication;
public class LocationApp extends UiApplication {
public LocationApp() {
LocationMainScreen screen = new LocationMainScreen();
pushScreen(screen);
}
public static void main(String[] args) {
LocationApp app = new LocationApp();
app.enterEventDispatcher();
}
} LocationMainScreen.java:
package com.beginningblackberry.location;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.Menu;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.RichTextField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;
public class LocationMainScreen extends MainScreen {
private LabelField latitudeLabel;
private LabelField longitudeLabel;
private RichTextField messageField;
public LocationMainScreen() {
HorizontalFieldManager latManager = new HorizontalFieldManager();
latManager.add(new LabelField("Latitude:"));
latitudeLabel = new LabelField("");
latManager.add(latitudeLabel);
add(latManager);
HorizontalFieldManager longManager = new HorizontalFieldManager();
longManager.add(new LabelField("Longitude:"));
longitudeLabel = new LabelField("");
longManager.add(longitudeLabel);
add(longManager);
messageField = new RichTextField();
add(messageField);
}
private void update() {
}
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(new MenuItem("Update", 10, 10) {
public void run() {
update();
}
});
}
}

Using the location API is another one of those things; like networking, it must be done outside the UI thread. The reason should be clear: getting a fix on GPS satellites can take some time, so the UI thread shouldn’t be locked up. Follow a similar pattern to the Networking example and create a new class to handle the details of working with the location API. First, add a couple of methods to LocationMainScreen to enable the new class to display results to the screen. Add the following to LocationMainScreen:

public void setLocation(double longitude, double latitude) {
synchronized(UiApplication.getEventLock()) {
longitudeLabel.setText(Double.toString(longitude));
latitudeLabel.setText(Double.toString(latitude));
}
}
public void setMessage(String message) {
synchronized (UiApplication.getEventLock()) {
messageField.setText(message);
}
}

Location coordinates, as you might have guessed, are returned as double values representing the degrees of longitude and latitude. The message area gives you a freeform spot to print some other interesting information, such as the location method that was actually used and the accuracy of the results.Create a class called LocationHandler that extends Thread. It will contain an instance of LocationMainScreen so it can update the UI:

package com.beginningblackberry.location;
public class LocationHandler extends Thread {
private LocationMainScreen screen;
public LocationHandler(LocationMainScreen screen) {
this.screen = screen;
}
public void run() {
}
}

It’s time to start using the location API. Add the following imports to the top of
LocationHandler.java:

import javax.microedition.location.Criteria;
import javax.microedition.location.Location;
import javax.microedition.location.LocationException;
import javax.microedition.location.LocationProvider;
import javax.microedition.location.QualifiedCoordinates;

Now you fill in the run method. Basically you fill in the criteria as described earlier (use the Assisted GPS / Unassisted GPS hybrid) and get an instance of LocationProvider that you can then use to obtain an actual location. The code is fairly self-explanatory; we present it here and then discuss it:

public void run() {
Criteria criteria = new Criteria();
criteria.setVerticalAccuracy(50);
criteria.setHorizontalAccuracy(50);
criteria.setCostAllowed(true);
criteria.setPreferredPowerConsumption(
Criteria.POWER_USAGE_HIGH);
try {
screen.setMessage("Getting location...");
LocationProvider provider =
LocationProvider.getInstance(criteria);
Location location = provider.getLocation(-1);
QualifiedCoordinates qualifiedCoordinates =
location.getQualifiedCoordinates();
screen.setLocation(qualifiedCoordinates.getLongitude(),
qualifiedCoordinates.getLatitude());
String message = "Successfully got location, method:";
int method = location.getLocationMethod();
if ((method & Location.MTA_ASSISTED) ==
Location.MTA_ASSISTED) {
message += " Assisted GPS";
}
if ((method & Location.MTA_UNASSISTED) ==
Location.MTA_UNASSISTED) {
message += " Unassisted GPS";
}
if ((method & Location.MTE_CELLID) ==
Location.MTE_CELLID) {
message += " Cell Site";
}
message += "\nHorizontal (Longitude) Accuracy: ";
message += qualifiedCoordinates.getHorizontalAccuracy();
message += "\nVertical (Latitude) Accuracy: ";
message += qualifiedCoordinates.getVerticalAccuracy();
screen.setMessage(message);
} catch (LocationException e) {
screen.setMessage("LocationException: " +
e.getMessage());
} catch (InterruptedException e) {
screen.setMessage("InterruptedException: " +
e.getMessage());
}
}

The location method is determined by the criteria that you have specified. In this case, you’d expect it to be Assisted GPS based on the discussion earlier. We’ve specified –1 as the parameter to LocationProvider.getLocation. This is the timeout parameter in milliseconds. –1 means you use the default for that provider. The Location you receive is qualified; that is, there’s some degree of error associated with it, represented by the accuracy values in the QualifiedCoordinates class. GPS coordinates will always be qualitifed. The unqualified Coordinates class is used mainly to specify coordinates that you want plotted on a map. Finally, don’t forget to fill out the update method in LocationMainScreen:

private void update(){
LocationHandler handler = new LocationHandler(this);
handler.start();
}

Now start the simulator or load on to your device and give it a try.

NOTE: that if you’re running on the simulator, you can simulate a GPS location from the Simulate ➤ GPS Location menu. Click Update, and you should see your current latitude and longitude.

Getting the device’s location using Assisted GPS

Getting the device’s location using Assisted GPS

Feel free to substitute some of the other criteria values from the previous location modes section to see how they affect things. You should notice that Cell Site location is much quicker than a GPS mode, but generally doesn’t have nearly as good accuracy.In many applications, a good approach is to get a rough idea of the user’s location using the Cell Site mode, and then refine it using GPS if and when it’s available.

Getting Periodic Location Updates Using LocationListener

The location API provides a method to receive regular updates of the device’s location using the LocationListener interface.You specify an interval to receive notifications at and a maximum age parameter to indicate how recent the location results must be.Setting a maximum age enables the device to re-use previous location information from the GPS provider. Establishing a GPS location uses processor power and battery life (and potentially network data), so you should specify maximum age as large as possible to help the user’s device run efficiently.

You will add support for periodic updates to your application. Because you want essentially the same functionality for an automatic location update asfor a manual location update, you need LocationHandler to act as the LocationListener and move some code around. First, add an import for LocationListener and change the signature of LocationListener to implement the interface. Also add a boolean flag to indicate whether you want to register for periodic location updates and a constructor to initialize the flag. So you can see your coordinates update, add one more thing, a Vector to store a list of the coordinates, so you can display the distance between location updates:

import java.util.Vector;
import javax.microedition.location.LocationListener;
//...
public class LocationHandler extends Thread implements LocationListener {
private LocationMainScreen screen;
private boolean periodicUpdates;
private Vector coordinateHistory = new Vector();
public LocationHandler(LocationMainScreen screen, boolean update) {
this.screen = screen;
this.periodicUpdates = update;
}

LocationListener includes two methods: providerStateChanged, which is invoked whenever the availability of the provider specified by the location criteria changes (for example, if GPS coverage is lost) and locationUpdated, which gives us the actual location updates. For this application you’ll provide an empty implementation for providerStateChanged, though in a real-world application you’d generally want to take some action:

public void providerStateChanged(LocationProvider provider, int newState){
// Do nothing for our application
}

The implementation of locationUpdated is taken directly from the run method of LocationHandler. Add a timestamp to the message so you can see the location being updated in the application. Also check to see if there were previous coordinates (if the history isn’t empty) and display the distance between the current set and the last set of coordinates. First, add the following imports to LocationHandler.java to bring in the date/time and coordinate-handling classes:

import net.rim.device.api.i18n.SimpleDateFormat;
import java.util.Date;
import javax.microedition.location.Coordinates;

The locationUpdatedMethod follows:

public void locationUpdated(LocationProvider provider, Location location) {
QualifiedCoordinates qualifiedCoordinates =
location.getQualifiedCoordinates();
screen.setLocation(qualifiedCoordinates.getLongitude(),
qualifiedCoordinates.getLatitude());
String message = "Successfully got location at ";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
message += simpleDateFormat.format(new Date(location.getTimestamp()));
if (coordinateHistory.size() > 0) {
Coordinates lastCoordinates =
(Coordinates)coordinateHistory.lastElement();
message += "\nDistance from last update:" +
lastCoordinates.distance(qualifiedCoordinates);
}
coordinateHistory.addElement(qualifiedCoordinates);
message += "\nMethod:";
int method = location.getLocationMethod();
if ((method & Location.MTA_ASSISTED) == Location.MTA_ASSISTED) {
message += " Assisted GPS";
}
if ((method & Location.MTA_UNASSISTED) == Location.MTA_UNASSISTED) {
message += " Unassisted GPS";
}
if ((method & Location.MTE_CELLID) == Location.MTE_CELLID) {
message += " Cell Site";
}
message += "\nHorizontal (Longitude) Accuracy: ";
message += qualifiedCoordinates.getHorizontalAccuracy();
message += "\nVertical (Latitude) Accuracy: ";
message += qualifiedCoordinates.getVerticalAccuracy();
screen.setMessage(message);
}

Coordinates have a handy built-in method that can calculate distance in mneters between two geographical locations. You use that here. The interval is ten seconds. Usually, the first acquisition of GPS satellites takes longer than that, but after that’s done, subsequent updates can happen quickly.

NOTE: net.rim.device.api.i18n.SimpleDateFormat is an easy way to formatdate/time values into strings. The output format is specified using a formatstring, where different letters specify different components of the date/time to display. For example, if you have a Date object representing August 12, 2007, 9:57 p.m, you can get the following representations:
EEEE, MMMM dd yyyy at HH:mm:ss would give Sunday, August 12, 2007 at
21:57
hh:mm:ss a would give 9:57 PM
yyyy-MM-dd would give 2007-08-12
A full explanation of all the format characters is available in the Javadocs for SimpleDateFormat.

The run method will change to optionally add the listener and to remove the code that updates the UI in favor of calling locationUpdated. Replace the current try/catch block in LocationHandler.run() with the following:

try {
screen.setMessage("Getting location...");
LocationProvider provider =
LocationProvider.getInstance(criteria);
Location location = provider.getLocation(-1);
locationUpdated(provider, location);
if (periodicUpdates) {
provider.setLocationListener(this, 30, -1, -1);
}
} catch (LocationException e) {
screen.setMessage("LocationException occurred getting location:
" + e.getMessage());
} catch (InterruptedException e) {
screen.setMessage("InterruptedException occurred getting
location: " + e.getMessage());
}

You have set the location provider for an update every 30 seconds.Finally, change the update method in LocationMainScreen to call the new constructor:

private void update() {
LocationHandler handler = new LocationHandler(this, true);
handler.start();
}

Start the application, select Update, and leave the application running. You’ll see the location updated every 30 seconds. If you’re running on a real device, walk around a bit to see your location being tracked!

Device location after a periodic update

Device location after a periodic update



Face Book Twitter Google Plus Instagram Youtube Linkedin Myspace Pinterest Soundcloud Wikipedia

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

BLACKBERRY Topics