Retrieving the optimal fix with GPS and geolocation

You can retrieve the optimal location fix by requesting geolocation updates along with GPS updates. An optimal fix provides a geolocation fix when a GPS fix cannot be retrieved during the specified timeout period. You can use this request in an application that requires the location of a BlackBerry device at all times, and you are not concernced about how the location is retrieved.

The BlackBerryCriteria class, in the net.rim.device.api.gps package, provides the following methods for retrieving the optimal fix:

Method

Description

enableGeolocationWithGPS()

This method returns a GPS fix as soon as it is available or within the timeout period that is specified in the location request. If the GPS fix is unavailable, a geolocation fix is returned. You can use this method for single or multiple fix requests.

enableGeolocationWithGPS(BlackBerryCriteria.FASTEST_FIX_PREFERRED)

This method returns the first available fix, regardless of the location source (GPS or geolocation). During the timeout period that is specified in the location request, the first fix that is available from a location source is provided to the application. You can use this mode only for single fix requests.

Retrieve the optimal single fix

The following steps demonstrate how to create a UI application that provides the fastest available location fix, which may come from a geolocation or GPS location source. The location coordinates and the mode that the application uses to retrieve the location are displayed on the screen.

Before you begin: Verify that the BlackBerry device or BlackBerry Smartphone Simulator can access the geolocation service.
  1. Import the required classes and interfaces.
    import net.rim.device.api.gps.*;
    import net.rim.device.api.system.Application;
    import net.rim.device.api.ui.*;
    import net.rim.device.api.ui.component.*;
    import net.rim.device.api.ui.container.*;
    import javax.microedition.location.*;
  2. Create the application framework by extending the UiApplication class. In main(), create an instance of the new class and invoke enterEventDispatcher() to enable the application to receive events. In the application constructor, invoke pushScreen() to display the custom screen for the application. The SingleFixScreen class, which is described in step 3, represents the custom screen.
    public final class SingleFixDemo extends UiApplication
    {
        public static void main(String[] args)
        {
            SingleFixDemo theApp = new SingleFixDemo();
            theApp.enterEventDispatcher();
        }
        
        public SingleFixDemo() 
        {
            pushScreen(new SingleFixScreen());
        }
    }
  3. Create the framework for the custom screen by extending the MainScreen class. Create an instance of the LabelField class to store the coordinates that you want to display on the screen. Create two double variables to store the values for latitude and longitude . Create an integer variable and a String variable to store the location mode.
    class SingleFixScreen extends MainScreen 
    {
        private LabelField _coordLabel;
        private double _latitude;
        private double _longitude;
        private int _modeUsed;
        private String _mode;
    }
  4. In the screen constructor, invoke super() to create a default menu. Invoke setTitle() to specify the title for the screen.
    public SingleFixScreen() 
    {
        super(DEFAULT_CLOSE | DEFAULT_MENU);
        setTitle(new LabelField("Single Fix Demo", Field.USE_ALL_WIDTH | 
                DrawStyle.HCENTER));
    }
  5. In the screen constructor, create an instance of the ButtonField class to create a button that the BlackBerry device user clicks to retrieve the location of the device. Invoke Field.setChangeListener() to listen for changes to the button. Invoke findLocation(), which is described in step 6, to retrieve the geolocation when the user clicks the button. Invoke add() to add the button to the screen. Create an instance of the LabelField class to display the resulting coordinates and invoke add() to add the field to the screen.
    ButtonField locButton = new ButtonField("Get location fix", 
            ButtonField.CONSUME_CLICK);
    locButton.setChangeListener(new FieldChangeListener()
    {
        public void fieldChanged(Field field, int context)
        {
            findLocation();
        }
    });
    add(locButton);
            
    this._coordLabel = new LabelField();
    add(this._coordLabel);
  6. Create the framework for the findLocation method. Invoke setText() with an empty String value to clear LabelField for the coordinates. Create an instance of the Thread class that invokes run(). This thread is used to process the retrieval of the location information. In run(), create a try/catch block to specify the criteria for retrieving a location. Create an instance of the BlackBerryCriteria class by invoking BlackBerryCriteria(). No arguments are passed to BlackBerryCriteria(), so the default location mode is used. Invoke enableGeolocationWithGPS(BlackBerryCriteria.FASTEST_FIX_PREFERRED) to retrieve the first available location fix. In the catch block, invoke showException(), which is described in step 10, to display the error message for an UnsupportedOperationException.
    private void findLocation()
    {
        this._coordLabel.setText("");
                   
        Thread locThread = new Thread() 
        {
            public void run() 
            {
                try
                {
                    BlackBerryCriteria myCriteria = new BlackBerryCriteria();
                    myCriteria.enableGeolocationWithGPS(BlackBerryCriteria
                            .FASTEST_FIX_PREFERRED);
                } 
                catch (UnsupportedOperationException e) 
                {
                   showException(e);
                }
            }
        };
        locThread.start();
    }
  7. In the first try block, create a second try/catch block to retrieve a location provider. Invoke LocationProvider.getInstance() with the BlackBerryCriteria object to retrieve a location provider. In the catch block, invoke showException(), which is described in step 10, to display the error message for a LocationException.
    try
    {
        BlackBerryLocationProvider myProvider = (BlackBerryLocationProvider)
                LocationProvider.getInstance(myCriteria);
    }
    catch (LocationException e)
    {
        showException(e);
    }
  8. In the second try block, create a third try/catch block to retrieve the location information. Invoke BlackBerryLocationProvider.getLocation() with a parameter of -1 to retrieve a location provider by using the default timeout value. Invoke getLongitude() and getLatitude() to retrieve the longitudinal and latitudinal coordinates respectively. Invoke getGPSMode() to retrieve the mode that is used to retrieve the location. Create a switch block to identify whether the mode used is GPS or geolocation. Create an instance of the StringBuffer class and append the resulting coordinates and mode to the buffer. Create a String variable and invoke toString() with the StringBuffer object to return the String value for the coordinates. Invoke showResults() to display the results on the screen, which is described in step 9. In the first catch block, invoke showException(), which is described in step 10, to display the error message for an InterruptedException. In the second catch block, invoke showException(), which is described in step 10, to display the error message for a LocationException.
    try
    {
        BlackBerryLocation myLocation =(BlackBerryLocation)myProvider
                .getLocation(-1);
        _longitude = myLocation.getQualifiedCoordinates().getLongitude();
        _latitude = myLocation.getQualifiedCoordinates().getLatitude();
        _modeUsed = myLocation.getGPSMode();
                                    
        switch (_modeUsed)
        {
            case LocationInfo.GEOLOCATION_MODE:
            case LocationInfo.GEOLOCATION_MODE_CELL:
            case LocationInfo.GEOLOCATION_MODE_WLAN:
                _mode = "Geolocation";
                break;
            default:
                _mode = "GPS";
        }    
            
        StringBuffer sb = new StringBuffer();
        sb.append("Longitude: ");
        sb.append(_longitude);
        sb.append("\n");
        sb.append("Latitude: ");
        sb.append(_latitude);
        sb.append("\n");
        sb.append("Mode: ");
        sb.append(_mode);
        String msg = sb.toString();
        showResults(msg);
    }
    catch (InterruptedException e)
    {
        showException(e);
    }
    catch (LocationException e)
    {
        showException(e);
    }
  9. In the showResults method, invoke invokeLater() to add this section of code to the event queue of the application. Create an instance of the Runnable class and pass it as a parameter to invokeLater(). Override run() in the definition of Runnable. Invoke setText() with the String variable to specify the resulting coordinates for LabelField.
    private void showResults(final String msg)
    {
        Application.getApplication().invokeLater(new Runnable()
        {
            public void run()
            {
                SingleFixScreen.this._coordLabel.setText(msg);
            }
        });
    }
  10. In the showException method, invoke invokeLater() to add this section of code to the event queue of the application. Create an instance of Runnable and pass it as a parameter to invokeLater(). Override run() in the definition of Runnable. Invoke Dialog.alert() to create an alert dialog box, and pass the error message by invoking getMessage().
    private void showException(final Exception e) 
    {
        Application.getApplication().invokeLater(new Runnable()
        {
            public void run()
            {
                Dialog.alert(e.getMessage());
            }
        });
    }
Back To Top

Code sample: Retrieving the optimal single fix

The following code sample demonstrates how to create a UI application that provides the fastest available location fix, which may come from a geolocation or GPS location source.

import net.rim.device.api.gps.*;
import net.rim.device.api.system.Application;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.component.*;
import javax.microedition.location.*;

public final class SingleFixDemo extends UiApplication
{
    public static void main(String[] args)
    {
        SingleFixDemo theApp = new SingleFixDemo();
        theApp.enterEventDispatcher();
    }
    
    public SingleFixDemo() 
    {
        pushScreen(new SingleFixScreen());
    }
}

class SingleFixScreen extends MainScreen 
{
    private LabelField _coordLabel;
    private double _latitude;
    private double _longitude;
    private int _modeUsed;
    private String _mode;
          
    public SingleFixScreen() 
    {
        super(DEFAULT_CLOSE | DEFAULT_MENU);

        setTitle(new LabelField("Single Fix Demo" , Field.USE_ALL_WIDTH | 
                DrawStyle.HCENTER));
                     
        ButtonField locButton = new ButtonField("Get location fix", 
                ButtonField.CONSUME_CLICK);
        locButton.setChangeListener(new FieldChangeListener()
        {
            public void fieldChanged(Field field, int context)
            {
                findLocation();
            }
        });
        add(locButton);
        
        this._coordLabel = new LabelField();
        add(this._coordLabel);
    }
    
    private void findLocation()
    {
        this._coordLabel.setText("");
               
        Thread locThread = new Thread() 
        {
            public void run() 
            {
                try
                {
                    BlackBerryCriteria myCriteria = new BlackBerryCriteria();
                    myCriteria.enableGeolocationWithGPS(BlackBerryCriteria
                            .FASTEST_FIX_PREFERRED);
                    try
                    {
                        BlackBerryLocationProvider myProvider = 
                                (BlackBerryLocationProvider)LocationProvider
                                .getInstance(myCriteria);
                        try
                        {
                            BlackBerryLocation myLocation = (BlackBerryLocation)
                                    myProvider.getLocation(-1);
                            _longitude = myLocation.getQualifiedCoordinates()
                                    .getLongitude();
                            _latitude = myLocation.getQualifiedCoordinates()
                                    .getLatitude();
                            _modeUsed = myLocation.getGPSMode();
                            
                            switch (_modeUsed)
                            {
                                case LocationInfo.GEOLOCATION_MODE:
                                case LocationInfo.GEOLOCATION_MODE_CELL:
                                case LocationInfo.GEOLOCATION_MODE_WLAN:
                                    _mode = "Geolocation";
                                    break;
                                default:
                                    _mode = "GPS";
                            }    
                            
                            StringBuffer sb = new StringBuffer();
                            sb.append("Longitude: ");
                            sb.append(_longitude);
                            sb.append("\n");
                            sb.append("Latitude: ");
                            sb.append(_latitude);
                            sb.append("\n");
                            sb.append("Mode: ");
                            sb.append(_mode);
                            String msg = sb.toString();
                            showResults(msg);
                        }
                        catch (InterruptedException e)
                        {
                            showException(e);
                                                    }
                        catch (LocationException e)
                        {
                            showException(e);
                        }
                    }
                    catch (LocationException e)
                    {
                        showException(e);
                    }
               } 
               catch (UnsupportedOperationException e) 
               {
                   showException(e);
               }
            }
        };
        locThread.start();
    }

    private void showResults(final String msg)
    {
        Application.getApplication().invokeLater(new Runnable()
        {
            public void run()
            {
                SingleFixScreen.this._coordLabel.setText(msg);
            }
        });
    }
    
    private void showException(final Exception e) 
    {
        Application.getApplication().invokeLater(new Runnable() 
        {
            public void run() 
            {
                Dialog.alert(e.getMessage());
            }
        });
    }
}
Back To Top

Retrieve optimal multiple fixes

The following steps demonstrate how to create a UI application that provides continuous location updates by retrieving GPS fixes when the fixes are available or within the specified timeout period. If the GPS fix is unavailable, a geolocation fix is returned instead.

Before you begin: Verify that the BlackBerry device or BlackBerry Smartphone Simulator has GPS enabled.
  1. Import the required classes and interfaces.
    import net.rim.device.api.gps.*;
    import net.rim.device.api.system.Application;
    import net.rim.device.api.ui.*;
    import net.rim.device.api.ui.component.*;
    import net.rim.device.api.ui.container.*;
    import javax.microedition.location.*;
  2. Create the application framework by extending the UiApplication class. Create an integer variable and assign it a value of 1, which specifies the interval to update the location coordinates. Create a variable with the type EditField to store the location updates that displays on the screen. In main(), create an instance of the new class and invoke enterEventDispatcher() to enable the application to receive events. In the application constructor, create an instance of the MultipleFixScreen class, which is described in step 7. Invoke setTitle() to specify the title for the screen. Create an instance of the EditField class and add the field to the screen. Invoke startLocationUpdate(), which is described in step 4, to start retrieving location updates. Invoke pushScreen() to display the custom screen for the application.
    public class MultipleFixDemo extends UiApplication 
    {    
        private static int _interval = 1;
        private EditField _status;    
        
        public static void main(String[] args)
        {
            new MultipleFixDemo().enterEventDispatcher();
        }
    
        public MultipleFixDemo()
        {
            MultipleFixScreen screen = new MultipleFixScreen();
            screen.setTitle("Multiple Fix Demo");
            
            _status = new EditField(Field.NON_FOCUSABLE);
            screen.add(_status);
            
            startLocationUpdate();
            pushScreen(screen);
        }
    }
  3. Create an updateLocationScreen method that invokes invokeLater() to add this section of code to the event queue of the application. Create an instance of the Runnable class and pass it as a parameter to invokeLater(). Override run() in the definition of Runnable. Invoke setText() to display the results on the screen.
    private void updateLocationScreen(final String msg)
    {
        invokeLater(new Runnable()
        {
            public void run()
            {
                _status.setText(msg);
            }
        });
    }
  4. Create the framework for the startLocationUpdate method. Create a try/catch block for specifying the criteria to retrieve a location. Create an instance of the BlackBerryCriteria class by invoking BlackBerryCriteria(). The default location mode is used because no arguments are passed to BlackBerryCriteria(). Invoke enableGeolocationWithGPS() to specify retrieving a GPS fix if it's available, or retrieving a geolocation fix if the GPS fix is unavailable. In the catch block, catch an UnsupportedOperationException, which indicates the location mode is unsupported.
    private void startLocationUpdate()
    {
        try
        {
            BlackBerryCriteria myCriteria = new BlackBerryCriteria();
            myCriteria.enableGeolocationWithGPS();
        catch (UnsupportedOperationException ue)
        {
            System.err.println("Require mode is unavailable");
            System.err.println(ue); 
            System.exit(0);   
        }
        return;
    }
  5. In the first try block, create a second try/catch block to retrieve a location provider. Invoke LocationProvider.getInstance() with the BlackBerryCriteria object to retrieve a location provider. Create an instance of Runnable and pass it as a parameter to invokeLater(). Override run() in the definition of Runnable and display a message that indicates the location provider could not be retrieved. Invoke setLocationListener() by passing the interval value, timeout value, and maximum age as parameters to register a listener when a location provider is available. In the catch block, catch a LocationException, which indicates the location provider is unavailable.
    try
    {
        BlackBerryLocationProvider myProvider = (BlackBerryLocationProvider)
                LocationProvider.getInstance(myCriteria);
                    
        if ( myProvider == null )
        {
            Runnable showUnsupportedDialog = new Runnable() 
            {
                public void run() 
                {
                    Dialog.alert("Location service unsupported, exiting...");
                    System.exit( 1 );
                }
             };
             invokeLater( showUnsupportedDialog );  
         }
         else
         {
             myProvider.setLocationListener(new LocationListenerImpl(), 
                     _interval, 1, 1);
                 
         }
    }
    catch (LocationException le)
    {
        System.err.println("Failed to retrieve a location provider");
        System.err.println(le); 
        System.exit(0);
    }
  6. Create a second class that implements LocationListener. Implement locationUpdated() to provide location updates. Create an if statement to check that the location is valid. If the location is valid, retrieve the coordinates for the longitude, latitude, and altitude by invoking getLongitude(), getLatitude() and getAltitude() respectively. Create an instance of the StringBuffer class and append the resulting coordinates to the buffer. Invoke updateLocationScreen() to display the resulting coordinates on the screen.
    private class LocationListenerImpl implements LocationListener
    {
        public void locationUpdated(LocationProvider provider, Location location)
        {
            if(location.isValid())
            {
                double longitude = location.getQualifiedCoordinates()
                        .getLongitude();
                double latitude = location.getQualifiedCoordinates()
                        .getLatitude();
                float altitude = location.getQualifiedCoordinates()
                        .getAltitude();
                                    
                StringBuffer sb = new StringBuffer();
                sb.append("Longitude: ");
                sb.append(longitude);
                sb.append("\n");
                sb.append("Latitude: ");
                sb.append(latitude);
                sb.append("\n");
                sb.append("Altitude: ");
                sb.append(altitude);
                sb.append(" m");
                MultipleFixDemo.this.updateLocationScreen(sb.toString());
            }
        }
      
        public void providerStateChanged(LocationProvider provider, int newState)
        {
            // Not implemented
        }        
    }
  7. Create the framework for the custom screen by extending the MainScreen class. In the screen constructor, invoke super() to create a default menu. Create an instance of the RichTextField to display an instructional message. Invoke add() to add the RichTextField to the screen.
    private final static class MultipleFixScreen extends MainScreen
    {
        MultipleFixScreen()
        {
            super(DEFAULT_CLOSE | DEFAULT_MENU);
             
            RichTextField instructions = new RichTextField(
                    "Waiting for location update...",Field.NON_FOCUSABLE);
            this.add(instructions);
        }
    } 
Back To Top

Code sample: Retrieving optimal multiple fixes

The following code sample demonstrates how to create a UI application that provides continuous location updates by retrieving GPS fixes when the fixes are available or within the specified timeout period. If the GPS fix is unavailable, a geolocation fix is returned instead.

import net.rim.device.api.gps.*;
import net.rim.device.api.system.Application;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import javax.microedition.location.*;

public class MultipleFixDemo extends UiApplication 
{    
    private static int _interval = 1;
    private EditField _status;    
    
    public static void main(String[] args)
    {
        new MultipleFixDemo().enterEventDispatcher();
    }

    public MultipleFixDemo()
    {
        MultipleFixScreen screen = new MultipleFixScreen();
        screen.setTitle("Multiple Fix Demo");
        
        _status = new EditField(Field.NON_FOCUSABLE);
        screen.add(_status);
        
        startLocationUpdate();
        pushScreen(screen);
    }
       
    private void updateLocationScreen(final String msg)
    {
        invokeLater(new Runnable()
        {
            public void run()
            {
                _status.setText(msg);
            }
        });
    }

   private void startLocationUpdate()
    {
        try
        {
            BlackBerryCriteria myCriteria = new BlackBerryCriteria();
            myCriteria.enableGeolocationWithGPS();
            try
            {
                BlackBerryLocationProvider myProvider = 
                        (BlackBerryLocationProvider)LocationProvider
                        .getInstance(myCriteria);
                
                if ( myProvider == null )
                {
                    Runnable showUnsupportedDialog = new Runnable() 
                    {
                        public void run() {
                            Dialog.alert("Location service unsupported, 
                                    exiting...");
                            System.exit( 1 );
                        }
                    };
                    invokeLater( showUnsupportedDialog );  
                }
                else
                {
                    myProvider.setLocationListener(new LocationListenerImpl(), 
                            _interval, 1, 1);
                
                }
            }
            catch (LocationException le)
            {
                System.err.println("Failed to retrieve a location provider");
                System.err.println(le); 
                System.exit(0);
            }
        }
        catch (UnsupportedOperationException ue)
        {
            System.err.println("Require mode is unavailable");
            System.err.println(ue); 
            System.exit(0);   
        }
        return;
    }
    
    
    private class LocationListenerImpl implements LocationListener
    {
        public void locationUpdated(LocationProvider provider, 
                Location location)
        {
            if(location.isValid())
            {
                double longitude = location.getQualifiedCoordinates()
                        .getLongitude();
                double latitude = location.getQualifiedCoordinates()
                        .getLatitude();
                float altitude = location.getQualifiedCoordinates()
                        .getAltitude();
                                
                StringBuffer sb = new StringBuffer();
                sb.append("Longitude: ");
                sb.append(longitude);
                sb.append("\n");
                sb.append("Latitude: ");
                sb.append(latitude);
                sb.append("\n");
                sb.append("Altitude: ");
                sb.append(altitude);
                sb.append(" m");
                MultipleFixDemo.this.updateLocationScreen(sb.toString());
            }
        }
  
        public void providerStateChanged(LocationProvider provider, 
                 int newState)
        {
            // Not implemented
        }        
    }
       
    private final static class MultipleFixScreen extends MainScreen
    {
        MultipleFixScreen()
        {
            super(DEFAULT_CLOSE | DEFAULT_MENU);
            
            RichTextField instructions = new RichTextField(
                    "Waiting for location update...",Field.NON_FOCUSABLE);
            this.add(instructions);
        }
    }     
}
Back To Top

Was this information helpful? Send us your comments.