Wednesday, June 29, 2011

Location API and Google Maps in Android - Tutorial


Lars Vogel

Version 1.4
15.06.2011
Revision History
Revision 0.115.06.2010Lars Vogel
created
Revision 0.2 - 1.418.06.2010 - 15.06.2011Lars Vogel
bugfixes and enhancements
Android Location API and Google Maps
This tutorial describes the usage of the Android Location API, the usage of Google Maps and the Geolocation API. It is based on Eclipse 3.6, Java 1.6 and Android 2.3.3 (Gingerbread).

1. Android Location API and Google Maps

1.1. Android Location API

Most Android devices allow to determine the current geolocation. This can be done via a GPS (Global Positioning System) device, via cell tower triangulation or via wifi networks for which the geolocation is known. Android provides the package "android.location" which provides the API to determine the current geo position.
The class "LocationManager" provides access to the location service . The Android device might have several providers available and you can select one of them. For a flexible selection of the best location provider use a "Criteria" object in which you can define how the provider should be selected.
You can register a "LocationListener" with the "LocationManager" and will receive periodic updates about the geoposition. The class "LocationProvider" is the superclass of the different location providers which deliver the information about the current location.
You can also register an Intent also allows to define a proximity alert, this alert will be triggered if the device enters a area given by a longitude, latitude and radius (proximity alert).

1.2. Google Maps

Google provides in the package "com.google.android.maps" a library for using Google Maps in Android. Google Maps is not part of the standard Open Source Platform Android and you require an additional key to use them. This key will be specified in the view which will be used to display the map.
To use Google Maps in your application you need to add the following uses-library statement to your AndroidManifest.xml file. The project creation wizard allow to do this automatically.

<uses-library android:required="true" android:name="com.google.android.maps"></uses-library>

   

The class "MapActivity" extends the class "Activity" and provides the life-cycle management and the services for displaying a Map in a "MapView". MapActivity is for maps what ListActivity is for lists.
A "MapView" is typically defined in the layout for the MapActivity and requires the API key in the attribute android:apiKey. A MapView can be used with other UI components in the same layout.
The class "MapController" can be used to interact with the "MapView", e.g. by moving it. A "Geopoint" is a position described via latitude and longitude and the class "Overlay" can be used to drawn on the map, for example position markers.
The usage of Google Maps also requires the permission to access the internet as the Google Maps data is read from it.

1.3. Forward and reverse Geocoding

The class "Geocoder" allow to determine the geo-coordinates (longitude, laditude) for a given address and vice versa.

1.4. Android Basics

The following assumes that you have already basic knowledge in Android development . Please check the Android development tutorialfor the basics.

2. Google Map key

To use Google Maps you need an additional key. See Obtaining a Maps API Key to learn how to get an Google Maps API key. This process is a little bit time consuming and involves creating a value on the command line as well as a webpage to get the key.

3. Android Device

3.1. Device with Google API


In case you want to use Google Maps in your emulator you have to create a device which supports the Google API's. This requires that you also install the "Google API" (see Android development tutorial ). During device creation select the target Google API's in the version of your SDK.


3.2. Setting the geoposition

You can set the geoposition the the Android emulator via telnet. Open a console and connect to your device. The port number of your device can be seen in the title area of your emulator.

telnet localhost 5554
   

Set the position via the following command.

geo fix 13.24 52.31

   

3.3. Activating the GPS module on the device

You also need to activate the GPS module in the emulator. If you do not activate it you receive "null" the first time you try to use. The Google Map activity should automatically activate the GPS device in the emulator but if you want to use the location manager directly you need to do this yourself. Currently their seems to be an issue with this. Just start Google Maps on the emulator, this will activate the GPS provider.

4. Android Location API

4.1. Create Project

Create a new project "de.vogella.android.locationapi.simple" with the Activity "ShowLocation". This example will not use the Google Map therefore select an Android target.
Define your view layout "main.xml" to the following.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical" android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <LinearLayout android:id="@+id/linearLayout1"
  android:layout_height="wrap_content" android:layout_width="match_parent"
  android:orientation="horizontal" android:layout_marginTop="40dip">
  <TextView android:text="Latitude: " android:layout_height="wrap_content"
   android:layout_width="wrap_content" android:id="@+id/TextView01" android:layout_marginLeft="10dip" android:layout_marginRight="5dip" android:textSize="20dip"></TextView>
  <TextView android:text="unknown" android:layout_height="wrap_content"
   android:layout_width="wrap_content" android:id="@+id/TextView02" android:textSize="20dip"></TextView>
 </LinearLayout>
 <LinearLayout android:id="@+id/linearLayout2"
  android:layout_height="wrap_content" android:layout_width="match_parent">
  <TextView android:text="Longitute: " android:layout_height="wrap_content"
   android:layout_width="wrap_content" android:id="@+id/TextView03"
   android:layout_marginLeft="10dip" android:layout_marginRight="5dip" android:textSize="20dip"></TextView>
  <TextView android:text="unknown" android:layout_height="wrap_content"
   android:layout_width="wrap_content" android:id="@+id/TextView04" android:textSize="20dip"></TextView>
 </LinearLayout>


</LinearLayout>

   

4.2. Add permissions

Add the following permissions to your application in Android.xml.
  • INTERNET
  • ACCESS_FINE_LOCATION
  • ACCESS_COARSE_LOCATION

4.3. Activity

Create the following activity. This activity will query the location manager and display the queried values in the activity.

package de.vogella.android.locationsapi.simple;

import android.app.Activity;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public class ShowLocation extends Activity implements LocationListener {
 private TextView latituteField;
 private TextView longitudeField;
 private LocationManager locationManager;
 private String provider;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  latituteField = (TextView) findViewById(R.id.TextView02);
  longitudeField = (TextView) findViewById(R.id.TextView04);

  // Get the location manager
  locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
  // Define the criteria how to select the locatioin provider -> use
  // default
  Criteria criteria = new Criteria();
  provider = locationManager.getBestProvider(criteria, false);
  Location location = locationManager.getLastKnownLocation(provider);

  // Initialize the location fields
  if (location != null) {
   System.out.println("Provider " + provider + " has been selected.");
   int lat = (int) (location.getLatitude());
   int lng = (int) (location.getLongitude());
   latituteField.setText(String.valueOf(lat));
   longitudeField.setText(String.valueOf(lng));
  } else {
   latituteField.setText("Provider not available");
   longitudeField.setText("Provider not available");
  }
 }

 /* Request updates at startup */
 @Override
 protected void onResume() {
  super.onResume();
  locationManager.requestLocationUpdates(provider, 400, 1, this);
 }

 /* Remove the locationlistener updates when Activity is paused */
 @Override
 protected void onPause() {
  super.onPause();
  locationManager.removeUpdates(this);
 }

 @Override
 public void onLocationChanged(Location location) {
  int lat = (int) (location.getLatitude());
  int lng = (int) (location.getLongitude());
  latituteField.setText(String.valueOf(lat));
  longitudeField.setText(String.valueOf(lng));
 }

 @Override
 public void onStatusChanged(String provider, int status, Bundle extras) {
  // TODO Auto-generated method stub

 }

 @Override
 public void onProviderEnabled(String provider) {
  Toast.makeText(this, "Enabled new provider " + provider,
    Toast.LENGTH_SHORT).show();

 }

 @Override
 public void onProviderDisabled(String provider) {
  Toast.makeText(this, "Disenabled provider " + provider,
    Toast.LENGTH_SHORT).show();
 }
}
   

4.4. Run and Test

Send some geo-coordinates to your device for example. These geo-coordinate should be displayed as soon as you press the button.

5. Google Maps

5.1. Create Project

Create a new project "de.vogella.android.locationapi.maps" with the activity "ShowMapActivity". Make sure to select the "Google API" als Target. Add also the same permissions as in the last example to your application.

5.2. Google Map library

You need to add the Google maps library to your application. Add "uses library" to "AndroidManifest.xml".

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="de.vogella.android.locationapi.maps" android:versionCode="1"
 android:versionName="1.0">
 <uses-sdk android:minSdkVersion="10" />

 <application android:icon="@drawable/icon" android:label="@string/app_name">
  <activity android:name=".ShowMap" android:label="@string/app_name">
   <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
  </activity>
  <uses-library android:required="true" android:name="com.google.android.maps"></uses-library>

 </application>
</manifest>
   

5.3. Layout

The next step requires that you have generated your Google Map key . Change the "main.xml" layout to the following. Replace "Your Maps API Key" with your Google API key.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainlayout"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <com.google.android.maps.MapView
        android:id="@+id/mapview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:clickable="true"
        android:apiKey="Your Maps API Key"
    />

</RelativeLayout>

   

5.4. Activity

Create the following activity. This activity use an LocationListner to update the map with the current location.

package de.vogella.android.locationapi.maps;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.RelativeLayout;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;

public class ShowMap extends MapActivity {

 private MapController mapController;
 private MapView mapView;
 private LocationManager locationManager;

 public void onCreate(Bundle bundle) {
  super.onCreate(bundle);
  setContentView(R.layout.main); // bind the layout to the activity

  // create a map view
  RelativeLayout linearLayout = (RelativeLayout) findViewById(R.id.mainlayout);
  mapView = (MapView) findViewById(R.id.mapview);
  mapView.setBuiltInZoomControls(true);
  mapView.setStreetView(true);
  mapController = mapView.getController();
  mapController.setZoom(14); // Zoon 1 is world view
  locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
  locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
    0, new GeoUpdateHandler());
 }

 @Override
 protected boolean isRouteDisplayed() {
  return false;
 }

 public class GeoUpdateHandler implements LocationListener {

  @Override
  public void onLocationChanged(Location location) {
   int lat = (int) (location.getLatitude() * 1E6);
   int lng = (int) (location.getLongitude() * 1E6);
   GeoPoint point = new GeoPoint(lat, lng);
   mapController.animateTo(point); // mapController.setCenter(point);
  }

  @Override
  public void onProviderDisabled(String provider) {
  }

  @Override
  public void onProviderEnabled(String provider) {
  }

  @Override
  public void onStatusChanged(String provider, int status, Bundle extras) {
  }
 }
}
 
   

5.5. Run and Test

Run and test your application. You should be able to zoon in and out and send new geocoordinates to your Maps via the Emulator console.


Tip

See also Hello, MapView for an example how to put graphics on the map.

6. Thank you

No comments:

Post a Comment