Thursday, November 20, 2008

GPS and MapView in Android

Having spent an evening hacking around writing an Android application that uses the GPS position together with the MapView component to show both your current location latitude/longitude and visually I spent a lot of time sifting through sites and blogs that used out of date APIs and overlooked crucial steps, so I thought I'd document how to enable GPS access and MapView usage using the Android Eclipse plugin and the emulator. This will then work when running on an Android device.

Step 1: GPS Access
Basic GPS access is relatively straightforward. You can use code like this in your Activity.onCreate() to get the current position and register a listener for position updates:

LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

List pro = lm.getAllProviders();
Location l = lm.getLastKnownLocation(LOCATION_SERVICE);

updatePositionOnScreen(l);

Intent i = new Intent(LOCATION_CHANGED);
LocationListener ll = new LocationListener() {
public void onLocationChanged(Location location) {
updatePositionOnScreen(location);
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30000, 100, ll);
In addition to this you need to add permissions to your Android manifest file to allow your application access to the location services:

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


For running your application in the Android emulator you will need mock position data, as there is no live GPS data from the emulator.

The easiest way to do this is to launch the emulator from Eclipse and then switch to the DDMS perspective (Window -> Open Perspective -> Other). Your Eclipse should then look something like the picture on the right.

This shows you a device browser on the left, w ith an Emulator Control tab underneath. Scroll down the Emulator Control tab until you see the Location Controls section. This allows you to enter mock location data to use when running the Emulator - the best way is to use a KML file, which you can create from Google Earth, or download a default location file from http://www.sunlightlabs.com/earmarks/house_defense_earmarks_08.kml. Once this has been imported click the green play button in the Location Controls (KML) section and your application will receive location updates based on the contents of the KML file.

Step 2: Google MapView component

The Google MapView component allows you to embed the Google map component in your application, so we can combine our live location data with a visual display of that location on a map. Embedding the MapView component has a few "tricky" steps:

Add the MapView component to your Activity:
<com.google.android.maps.MapView
android:id="@+id/mapview1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:enabled="true"
android:clickable="true"
android:apiKey="your api key"
/>

The apiKey attribute should be the MD5 fingerprint of your Maps API key. In order to deploy your MapView enabled application you need to register for a Google Maps API key, but for debugging you can use the Android SDK's debug key. All the details on Google Maps API keys can be found here http://code.google.com/android/toolbox/apis/mapkey.html, with details on how to obtain the debug SDK fingerprint here http://code.google.com/android/toolbox /apis/mapkey.html#getdebugfingerprint.

Once you have this, then to enable the MapView component you need to:
  • Change your Activity to extend MapActivity rather than Activity.
  • Add <uses-library android:name="com.google.android.maps"/> as a child of the element in the Android Manifest file.
  • Enable Internet access for your application so that it can download map data by adding <uses-permission android:name="android.permission.INTERNET"/> to your manifest file.
You can then add code to your application's location listener to update the MapView component to reflect the current position, such as:
MapView mapView = (MapView) findViewById(R.id.mapview1);
MapController mc = mapView.getController();

GeoPoint p = new GeoPoint((int) (l.getLatitude() * 1E6),
(int) (l.getLongitude() * 1E6));
mc.animateTo(p);
mc.setZoom(16);
mapView.invalidate();
When you run your application you should see your live MapView control responding to GPS lcoation updates, like below:

1 comment:

Martin said...
This comment has been removed by the author.