Tuesday, May 29, 2012

How to use GPS location services and Google Static Map API in J2ME MIDlets

oday, most mobile devices come with a GPS module or can connect to one using Bluetooth services. These devices come with support for the Location API for J2ME under JSR-179 that allow J2ME MIDlets applications to query the GPS module for geo-location coordinates. Also mobile applications integrate location based services and one increasingly used it to provide maps images using Google Maps or Google Static Maps. The later is accessible through Google Static Maps API V2, which is an open and free service (no longer requires a Maps API key) and more efficient as it minimizes network transfers.
In this article it is described and developed a fully MIDlet application that gets coordinates from the mobile device GPS module and use them to display a Google static map for that location. The application can be tested on the emulator or on a real device that has a GPS module incorporated.

You can download the full source code, including a sample test MIDlet.
If you have a mobile device that doesn’t have a GPS incorporated, this solution will not work because the J2ME Location API doesn’t have methods for connecting through Bluetooth to that external module. In this case, you need another solution (I will post it in another article) that
  • uses the Bluetooth API (JSR 82) to discover and to connect to the external GPS module;
  • parse the received GPS NMEA strings.

How to use J2ME Location API (JSR-179) and get the GPS coordinates

 

Midlet that displays GPS coordinates


In order to communicate with the phone GPS module and get data regarding coordinates, course, altitude or speed we need classes from javax.microedition.location.* package:
  • create a javax.microedition.location.Criteria instance, used to select the location provider; although there are multiple options (described by the JSR-179 documentation), their default values are the least restrictive; in this example we choose explicitly to allow a cost for the service (it’s free) and we don’t have a power consumption requirement; this step is not so important because the device has one GPS module and these are the criteria for selecting between multiple modules;
import javax.microedition.location.*;
...
        Criteria criteria = new Criteria();
        //same as default value
        criteria.setCostAllowed(true);
        //same as default value
        criteria.setPreferredPowerConsumption(Criteria.NO_REQUIREMENT);


  • obtain the location provider reference, a LocationProvider instance, using previous defined criteria and use it to query the GPS module for the current location; the getLocation() method has a timeout parameter indication how long we are willing to wait (seconds) for the data;
  • get the coordinates and extract the latitude and longitude; Attention ! the coordinates are returned as double and only the CLDC 1.1 supports floating point data processing (set the device configuration to CLDC 1.1 for this project because CLDC 1.0 does not support double type):


LocationProvider provider = null;
double latitude;
double longitude;
try {
	//get the location provider
        provider = LocationProvider.getInstance(criteria);
	//set a timeout of 60 seconds
        Location location = provider.getLocation(60);
	//get the coordinates
        Coordinates coordinates = location.getQualifiedCoordinates();
 
        if (coordinates != null) {
            //get the latitude and longitude of the coordinates
            latitude = coordinates.getLatitude();
            longitude = coordinates.getLongitude();
        } else {
            //no coordinates
        }
    } catch (LocationException ex) {
        System.out.println("Problems with location provider ! " +
		ex.getMessage());
        ex.printStackTrace();
    } catch (InterruptedException ex) {
	System.out.println(ex.getMessage());
        ex.printStackTrace();
    }
 
 
In the final application, the previous code sample is part of the getGPSData() method. This method defines a inner class that extends Thread because we want to query the GPS module on another thread than the main one. In this way, the application will respond to commands while it is waiting for the GPS to respond.

How to get GPS data on regular intervals

If you want to develop a J2ME application that will receive GPS coordinates on regular intervals (not the case for this example) you must define a handler used by the LocationProvider to notify the application. To do this, you must implement the LocationListener interface that has 2 abstract methods:
  • locationUpdated(LocationProvider provider, Location location) – method called by the provider at regular intervals to provide the current location;
  • providerStateChanged(LocationProvider provider, int newState) – method called by the provider to announce if its new state (LocationProvider.OUT_OF_SERVICE, LocationProvider.AVAILABLE, LocationProvider.TEMPORARILY_UNAVAILABLE);

public void locationUpdated(LocationProvider arg0, Location arg1) {
        if (arg1 != null && arg1.isValid()) {
            //get the coordinates
            Coordinates coordinates = arg1.getQualifiedCoordinates();
 
            if (coordinates != null) {
                //get the latitude and longitude of the coordinates.
                latitude = coordinates.getLatitude();
                longitude = coordinates.getLongitude();
 
            } else {
                //no valid coordinates
            }
        }
    }
 
    public void providerStateChanged(LocationProvider arg0, int arg1) {
        if (arg1 == LocationProvider.OUT_OF_SERVICE ||
                arg1 == LocationProvider.TEMPORARILY_UNAVAILABLE) {
            System.out.println("GPS inactive");
        }
    }
For setting the listener and to receive updates on location, we must register the listener using setLocationListener(LocationListener listener,int interval,int timeout,int maxAge) method:
	provider.setLocationListener(this, 60, -1, -1);
For the last call, the application will receive GPS updates at each 60 seconds with default timeout and max Age.

If you want to stop the updates (this consumes battery power), this is done calling one again the setLocationListener() method:
	provider.setLocationListener(null, -1, -1, -1);

How to use Google Static Map API

Google Static Maps is a free service offered by Google to developers that want to embed maps into their applications based on URL parameters sent through a simple HTTP query string without requiring JavaScript or any dynamic page loading. The service sends an image as response.
So, in order to get an 300×300 pixels map image for the 44.435251 latitude and 26.1024 longitude, with a moderate zoom, you make a HTTP request using:
http://maps.google.com/maps/api/staticmap?center=44.435251,26.1024&zoom=14&size=300×300&sensor=false

Link: How to use GPS location services and Google Static Map API in J2ME MIDlets _ IT&C Solutions