Android Application Development – Part 2


20 July 2011, by

previous article in series

Recap

In Part 1 we covered creating an Android application, adding a new text field to the view and programmatically setting the content of the new text field.

In this article, we’ll be retrieving GPS coordinates, and displaying them in the view.

Known issues

At time of writing there is a known problem working with R12 Android development, which results in the following message when you try to launch the emulator: invalid command-line parameter: Files. It’s a bug in the framework: the SDK location cannot contain any spaces. The default installation location is: C:Program Files (x86)Androidandroid-sdk. Google are currently working on a fix for the problem. You can work around it by changing the SDK location path in eclipse to: C:PROGRA~2Androidandroid-sdk (or C:PROGRA~1Androidandroid-sdk  for 32-bit Windows), or by creating a shortcut to your Android SDK and using that as the SDK location path in eclipse. Create a link using: MKLINK /J C:Android "C:Program Files (x86)Androidandroid-sdk"

At time of writing there is also a known issue with the Android 2.3 emulator, causing it to crash when GPS coordinates are sent to it. There is no known workaround: I recommend selecting a target either before or after Android 2.3.

Android’s GPS support

Before we start developing the application to make use of GPS coordinates, we’ll need to ensure that our emulator is receiving them.

The Android SDK provides good support for providing location information to the emulated device. There are a couple of ways to do it.

  • Using telnet. While the emulator is running, telnet to localhost, port 5554. There you can issue the command: geo fix <longitude> <latitude> [<altitude>]
    eg. geo fix -73.961452 40.714224 

    See: http://developer.android.com/guide/developing/tools/emulator.html#geo

    NB. At time of writing, this method introduces a small error to the coordinates as the figures entered via telnet seem to be interpreted rather than directly used. End result: your location as understood by the emulator may be out by a few streets…

  • Sending coordinates to the EmulatorUsing the SDK. This method is a little more integrated, and (at time of writing) does not experience the same bug as the telnet method.The Android SDK offers an Eclipse perspective called DDMS. Amongst other things, this perspective has lots of controls for manipulating the currently running device emulator.One of the available tabs is called ‘Emulator Control’ and in the bottom half, it shows a section called ‘Location Controls’. You can use the Manual tab to enter Longitude and Latitude data, and update the emulated location by clicking ‘Send’.

In order to make use of the GPS system in Android, you’ll need to know about a few classes.

  • LocationManager is a class representing Android’s Location Service – which manages GPS and location information.
  • LocationListener is an interface able to listen to retrieve update messages from the LocationManager class (through its onLocationChanged method).

Modifying the activity

Let’s go and edit GpsMonitoringActivity.java again. Here’s the new version:

public class GpsMonitoringActivity extends Activity {

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView v = (TextView)this.findViewById(R.id.TextView01);
        v.setText("Starting...");

        // Define a listener that responds to location updates -- new code from here:
        LocationListener locationListener = new LocationListener() {
            public void onLocationChanged(Location location) {
                // Called when a new location is found by the network location provider.
                makeUseOfNewLocation(location);
            }

            public void onStatusChanged(String provider, int status, Bundle extras) {}
            public void onProviderEnabled(String provider) {}
            public void onProviderDisabled(String provider) {}
        };

        try {
            // Acquire a reference to the system Location Manager
            LocationManager locationManager =
                (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
            // Register the listener with the Location Manager to receive location updates
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
        } catch (SecurityException e) {
            // requires ACCESS_FINE_LOCATION permission
            v.setText(e.getMessage());
        }
    }

    private void makeUseOfNewLocation(Location loc) {
        TextView v = (TextView)this.findViewById(R.id.TextView01);
        String text = "lat: " + loc.getLatitude() + ", long: " + loc.getLongitude();
        v.setText(text);
    }
}

Looking at the new code (from line 11 onwards), you can see that we’ve done quite a few things.

Creating a LocationListener

We’ve created an anonymous class that implements LocationListener – this will handle changes to location. Of the methods provided by LocationListener, we are interested in onLocationChanged – the method that the LocationManager will call to provide us with new location information.

As you can see, this method makes a direct call to makeUseOfNewLocation – a new method added to the Activity.

Registering with the LocationManager

Secondly, we’ve registered our listener with with the Location Service. In order to do this, we need to get hold of the LocationManager. We can do this by invoking Activity.getSystemService(Context.LOCATION_SERVICE). This provides an instance of LocationManager that we can then call requestLocationUpdates on.

As you can see, we’ve done this pretty simply – providing a few parameters to indicate that we’d like GPS information as and when it becomes available, and providing the LocationListener we want the to receive new location information from the LocationManager.

Permissions

As you’ll note from the try/catch in the code above, this application is going to need the ACCESS_FINE_LOCATION permission in order to be allowed to request location updates from the LocationManager. To get this permission, you’ll need to edit the application’s manifest.

  • Open the manifest, and flip to the Permissions tab
  • Now add a “Uses Permission” entry, and set its permission to: android.permission.ACCESS_FINE_LOCATION.

NB. If you haven’t set the right permission, you’ll get a SecurityException when you try to access the GPS device through the LocationManager – which conveniently carries the message: “requires ACCESS_FINE_LOCATION permission”.

If you’re looking at the XML for the manifest, you’ll just want to add this line inside the root manifest element:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Rendering the incoming coordinates

The makeUseOfNewLocation method does some very simple work – getting hold of the TextView we want to update, and passing in a new string with the new coordinates.

Give it a try now! Run the application, and pass in some coordinates via telnet to see what comes up on the screen.

Note that Android is pushing each new location to the application as it perceives that it has moved. The application has not defined when or how frequently Android should attempt to discover its location. We have opted not to interfere with settings already in place. In this way, we are able to make use of the location information without driving up battery use or affecting other applications.

Next Time…

In Part 3, we’ll be looking at making use of Google’s web services to reverse geolocate and find out some information about the streets nearby. Additionally, we’ll be making use of the Android API to indicate that we would like to receive regular updates to the location, and specify the frequency.

next article in series

Tags: , , , , , , ,

Categories: Mobile, Technical

«
»

Leave a Reply

* Mandatory fields


two + = 8

Submit Comment