Tutorial details

Integrating Google Maps in Android App | App Code for Sale | Preview

Integrating Google Maps in Android App | Android Tutorial

This tutorial is based on the component Google Maps
Download

Overview PAGE TOP

Maps are powerful and important components when we talk about mobile. Android platform is bundled with Google Maps in order to help developers to create location based applications.

This tutorial aims to explain and describe the Google Maps and Geolocation API integration process into an Android application.

In order to code the application, Eclipse 3.7.2 will be used as an IDE and Android Ice Cream Sandwich 4.0 as the platform.

Create the project PAGE TOP

Create a new project as shown in Figure 1 and 2. Make sure you check the Google APIs build target in order to benefit from the com.google.android.maps package.

Figure 1 Create new project

create_new_project25.png

Figure 2 Choose build target

choose_build_target.png

As a package name specify com.chupamobile.android.googlemaps and hit Finish. Now you have a brand new empty project with only one activity GoogleMapsActivity.java and one layout main.xml.

Initial configurations PAGE TOP

In order to embed Google Maps in your application, you must first get a valid key. The Google Maps API key is generated based on the key with which you sign your application during development.

Eclipse auto-generates a so called “debug key” for your application. If you did not change its path, you will find this key at C:\Users\YourUser.android\debug.keystore.

In order to obtain the Google Maps API key, you must use the “keytool” command from your JDK installation referencing to your “debug.keystore” to obtain a fingerprint:

keytool –list –keystore debug.keystore –storepass android –keypass android

Figure 3 Obtain fingerprint (MD5)

obtain_fingerprint.png

With this certificate fingerprint now you can obtain your Google Maps API key. Go to https://developers.google.com/android/maps-api-signup, fill in the “My certificate's MD5 fingerprint” with your fingerprint and hit “Generate API key”. Now you have your key.

To be able to use Google Maps in your application you must modify your AndroidManifest.xml:

  • specify INTERNET permission
  • insert line

Your AndroidManifest.xml should look like this:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.chupamobile.android.googlemaps"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="14" />

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

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".GoogleMapsActivity"
            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:name="com.google.android.maps" />
    </application>
</manifest>

Creating the layout PAGE TOP

Modify your main.xml layout file from /res/layout folder:

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

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

Change your GoogleMapsActivity in order to extend MapActivity and make the zoom controllers available through setBuiltInZoomControls(true) method. Your GoogleMapsActivity should look like this:

package com.chupamobile.android.googlemaps;

import android.os.Bundle;

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

public class GoogleMapsActivity extends MapActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //fetch the map view from the layout
        MapView mapView = (MapView) findViewById(R.id.mapview);

        //make available zoom controls
        mapView.setBuiltInZoomControls(true);
    }

    @Override
    protected boolean isRouteDisplayed() {

        return false;

    }
}

Running the project on an actual device or on the emulator should result the output presented in the figure below. With this simple configuration you are able to zoom and pan the map.

map_emulator.png

Show a particular location PAGE TOP

In order to lead the map to display a particular location, you must firstly create a GeoPoint object initialized with the desired latitude and longitude you wish to display and then use the animateTo(GeoPoint) method of a MapController to navigate to that location.

Add to your GoogleMapsActivity the following code in onCreate method:

package com.chupamobile.android.googlemaps;

import android.os.Bundle;

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

public class GoogleMapsActivity extends MapActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {

        . . .

        mapView.setBuiltInZoomControls(true);

        //latitude and longitude of Rome
        double lat = 41.889882;
        double lon = 12.479267;

        //create geo point
        GeoPoint point = new GeoPoint((int)(lat * 1E6), (int)(lon *1E6));

        //get the MapController object
        MapController controller = mapView.getController();

        //animate to the desired point
        controller.animateTo(point);

        //set the map zoom to 13
        // zoom 1 is top world view
        controller.setZoom(13);

        //invalidate the map in order to show changes
        mapView.invalidate();
    }
        . . .
}

You must firstly define your desired latitude and longitude (in our particular case we want, for example, to display the city of Rome). Then, create a GeoPoint object and initialize it with the latitude and longitude previously defined. Note that the GeoPoint class stores the values of its coordinates as integer values, so you must first multiply the values with 1E6 (i.e. 10^6).

Now that you have your point, it remains only to navigate to it. Here comes in help the MapController (a utility class used to manage panning and zooming of a map). All you have to do is to create a MapController object and call its animateTo(GeoPoint)method in order to display the map around that point. Optionally, you can set a zoom value for the map (1 <= zoomLevel <= 21).

Geolocation API PAGE TOP

Android provides a location framework that your application can use to determine the device's location (via WI-FI, GPS or cell tower triangulation) and compute addresses from coordinates and vice-versa.

Detecting current location PAGE TOP

Knowing your user’s current location enables your application to be friendlier and more useful by providing better information. There are two ways in which you can determine current location:

  • using GPS – most accurate, works only outdoors, but it consumes battery faster and doesn’t return the location as fast as expected
  • using Android’s Network Location Provider (through cell towers and WI-FI signals) – works indoors and outdoors, responds faster and uses less battery

Android platform leverages its location API through android.location package that is used to determine the current user location through a couple of classes:

  • LocationManager – provides access to the system location services. These services allow applications to obtain periodic updates of current geographical location or to notify when the device is in proximity of a given location.
  • LocationProvider – provides periodic reports on the location of the device. The location is stored into Location objects.

Change your GoogleMapsActivity in order to detect current location:

package com.chupamobile.android.googlemaps;

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

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 GoogleMapsActivity extends MapActivity implements LocationListener {

    private MapView mapView;
    private LocationManager locManager;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {


         . . .


        // invalidate the map in order to show changes
        mapView.invalidate();


        // Use the location manager through GPS
        locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
                0, this);

        //get the current location (last known location) from the location manager
        Location location = locManager
                .getLastKnownLocation(LocationManager.GPS_PROVIDER);


            //if location found display as a toast the current latitude and longitude
        if (location != null) {

            Toast.makeText(
                    this,
                    "Current location:\nLatitude: " + location.getLatitude()
                            + "\n" + "Longitude: " + location.getLongitude(),
                    Toast.LENGTH_LONG).show();
        } else {

            Toast.makeText(this, "Cannot fetch current location!",
                    Toast.LENGTH_LONG).show();
        }

//when the current location is found – stop listening for updates (preserves battery)
        locManager.removeUpdates(this);
    }




    @Override
    protected boolean isRouteDisplayed() {
        return false;

    }

    /* When the activity starts up, request updates */
    @Override
    protected void onResume() {
        super.onResume();
        locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
                0, this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        locManager.removeUpdates(this); //activity pauses => stop listening for updates
    }
        @Override
    public void onLocationChanged(Location location) {

    }


    @Override
    public void onProviderDisabled(String provider) {

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

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

    }
    . . .

}

At a first glance you may see that your activity now implements LocationListener interface which gives the activity the possibility to receive notifications from the LocationManager when the location has changed and to request location updates.

Next, the locationManager object is created and attached a GPS provider. Now the location will be listened from the GPS module. Note that you must have your GPS enabled on your device. If you want to listen your current location from the network provider (via WI-FI or cellular towers) change the GPSPROVIDER into NETWORKPROVIDER.

Getting the current location and store it into a Location object is done by calling getLastKnownLocation() method of the locationManager object. In order to display the coordinates attached to the Location object, you simply call getLatitude() and getLongitude() methods.

After the location has been detected, in order to preserve battery life, stop the locationManager object receiving any updates by calling its removeUpdates() method. This step is also done in onPause() method of the activity.

In order to run the application without security issues, the following permissions must be added to AndroidManifes.xml:

  • android.permission.ACCESS_COARSE_LOCATION
  • android.permission.ACCESS_FINE_LOCATION

Your manifest should look like this:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.chupamobile.android.googlemaps"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />

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

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".GoogleMapsActivity"
            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:name="com.google.android.maps" />
    </application>

</manifest> 

Displaying overlays (markers) on the map PAGE TOP

Most applications that integrate Google Maps API into their features, also display on the map various points of interest as a map-pin or any kind of drawing. In order to achieve this, Android platform has a couple of classes that come in help:

  • ItemizedOverlay – abstract class that consists of a list of OverlayItems that handles drawing a marker for every item.
  • OverlayItem – the basic component for an ItemizedOverlay and represents a particular point to display on map

We first start with extending the ItemizedOverlay class in order to provide it our own functionality. Create a new class named MyItemizedOverlay that will extend ItemizedOverlay. Your class should look like this:

package com.chupamobile.android.googlemaps;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.GestureDetector;
import android.view.MotionEvent;

import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;

public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem> {

    private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();

    public MyItemizedOverlay(Drawable defaultMarker, Context ctx) {
        super(boundCenterBottom(defaultMarker));

    }

    public void addOverlay(OverlayItem overlay) {
        mOverlays.add(overlay);
        populate();
    }

    public void clear() {

        mOverlays.clear();
        populate();
    }

    @Override
    protected OverlayItem createItem(int i) {
        return mOverlays.get(i);
    }

    @Override
    public int size() {
        return mOverlays.size();
    }

    @Override
    protected boolean onTap(int index) {
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event, MapView mapView){

        return false;
    }

}

Next, we want to add a marker at our current location. Firstly, download a pin-like icon, name it map_pin and place it into /res/drawable folder. Next, add to your GoogleMapsActivity the following piece of code:

import android.location.LocationManager;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.widget.Toast;

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

public class GoogleMapsActivity extends MapActivity implements LocationListener {

    private MapView mapView;
    private MyItemizedOverlay itemizedOverlay;

    private LocationManager locManager;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {

        . . .

        //if location found display as a toast the current latitude and longitude
        if (location != null) {

        . . .

        point = new GeoPoint((int)(location.getLatitude()*1E6),(int)(location.getLongitude() *1E6));

        controller.animateTo(point);

        } else {

            . . .

        }

        // fetch the drawable - the pin that will be displayed on the map
        Drawable drawable = this.getResources().getDrawable(R.drawable.map_pin);

        // create and add an OverlayItem to the MyItemizedOverlay list
        OverlayItem overlayItem = new OverlayItem(point, "", "");

        itemizedOverlay = new MyItemizedOverlay(drawable,this);
        itemizedOverlay.addOverlay(overlayItem);

        // add the overlays to the map
        mapView.getOverlays().add(itemizedOverlay);
        mapView.invalidate();

        //when the current location is found – stop listening for updates (preserves battery)
        locManager.removeUpdates(this);
    }

Running your application will output the following result:

map_with_marker.png

A marker is displayed at the current location of the emulator.

Get touched location and reverse geocoding PAGE TOP

Often you would like to know the coordinates of the point touched by the user on the map. Once you find these coordinates it’s relatively simple to find their associated address. This process is named reverse geocoding.

In order to find the coordinates of the touched point, you have to create another class that listens for touch events. This class will extend SimpleOnGestureListener, it will be named MyGestureDetector and will be an inner class of GoogleMapsActivity. The class should look like this:

class MyGestureDetector extends SimpleOnGestureListener {


        @Override
        public boolean onSingleTapConfirmed(MotionEvent event) {

            // fetch the correspondent point from the map
            GeoPoint p = mapView.getProjection().fromPixels((int) event.getX(),(int) event.getY());

            // create an overlay item and clear all others
            OverlayItem o = new OverlayItem(p, null, null);
            itemizedOverlay.clear();
            itemizedOverlay.addOverlay(o);

            // add the overlay item
            mapView.getOverlays().clear();
            mapView.getOverlays().add(itemizedOverlay);
            mapView.invalidate();

            Geocoder geoCoder = new Geocoder(getBaseContext(),
                    Locale.getDefault());

            // get the address based on the coordinates
            try {
                List<Address> addresses = geoCoder.getFromLocation(p.getLatitudeE6() / 1E6, p.getLongitudeE6() / 1E6, 1);

                addressString = "";
                if (addresses.size() > 0) {
                    for (int i = 0; i < addresses.get(0)
                            .getMaxAddressLineIndex(); i++)
                        addressString += addresses.get(0).getAddressLine(i)
                                + " - ";
                }

                Toast.makeText(getBaseContext(), addressString,
                        Toast.LENGTH_SHORT).show();

            } catch (IOException e) {
                e.printStackTrace();
            }

            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {
            return super.onFling(e1, e2, velocityX, velocityY);
        }

        @Override
        public boolean onDown(MotionEvent e) {
            return false;
        }
    }

In order to listen to events on touch events change the onTouchEvent() method of the MyItemizedOverlay class into this:

public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem> {

    private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
    private GestureDetector gestureDetector;

    . . .

    @Override
    public boolean onTouchEvent(MotionEvent event, MapView mapView) {

        // when the user lifts its finger
        if (gestureDetector.onTouchEvent(event)) {
            return true;
        }

        return false;
        }

    public GestureDetector getGestureDetector() {
            return gestureDetector;
        }

    public void setGestureDetector(GestureDetector gestureDetector) {
        this.gestureDetector = gestureDetector;
    }

The last thing you should do is to attach a GestureDetector to your MyItemizedOverlay added objects. In order to do this, add the following line of code into your GoogleMapsActivity after initializing the MyItemizedOverlay object:

. . .

itemizedOverlay = new MyItemizedOverlay(drawable,this);
itemizedOverlay.setGestureDetector(new GestureDetector(new MyGestureDetector()));
. . .

Now the application gives you the possibility to select any point on the map, draw a marker over it and display its address.

Conclusions PAGE TOP

By using Google Maps API you can enhance your application with geo-locating properties, geo-tracking capabilities and many other location based features. This tutorial explained briefly the main building blocks of integrating this API into your application.

13 Comments Leave a comment

Please login in order to leave a comment.

Newest first
  • rajaasad89 2014-05-11 18:20:13 Thread #153

    I want to know where you used the Google API key in this Tutorial. Kindly update please.

    • rajaasad89 2014-05-11 19:45:56

      I got it :P

  • yummyly.danna 2014-03-14 06:54:37 Thread #62

    hi guys, I need a tutorial for this kind of application: - an app that gets my location and shows it with a marker on Google map. - this app should have a button and when I click on it: It select from my database nearest restaurants (within any range, maybe 1 miles) and show them with markers on the map. =>of course restaurants are stored in the database with their names and coordinates (latitude & longitude).

    If anyone ever seen any tutorial to do such an app, please tell me. Thx

  • Blancer 2013-09-29 14:47:50 Thread #52

    Hi, I when I try to obtain my key from cmd, it says "keytool command is not recognized". what should I do?

  • prasanna.davu 2013-02-18 13:14:30 Thread #32

    hi sir ur material was so helpfull so i need a application like track the user location when user moves draw a line on map could u help me it's very urgent?

  • pandya 2013-01-11 09:09:36 Thread #26

    if u get grid view in emulator than try in RUN

    C:\Program Files\Java\jdk1.7.0\bin>keytool -v -list -alias androiddebugkey -keystore debug.keystore -storepass android -keypass android

    so u can get MD5 fingure print that can pass to https://developers.google.com/maps/documentation/android/v1/maps-api-signup?hl=sv-SE

    and get valid API key..... (Gaurang H. Pandya/golu(INDIA))

  • prabodha89 2012-11-07 08:21:30 Thread #23

    I'm newbee to android and Im getting a nullpont exeption when touchig the map. It Throws from the GeoPonit when getting the touched coorinates... please help

  • jonatas.freitas.986 2012-10-21 09:56:06 Thread #22

    Very thorough your tutorial, thx a lot !

  • subbu.subbareddy 2012-10-08 16:16:31 Thread #21

    awesome tutorial for googlemap coordinates,googlemaps and for reverse geocoding... this one is helpful for me... It's just like in a sentence "A sharp knife for thick wood".....

  • Tedrasoft 2012-09-22 19:32:00 Thread #20

    very helpful .. just what I needed for a project

  • abhijitfiasco 2012-09-21 13:57:40 Thread #19

    Very thorough, explicit and lucid. It should appear as a top search for "android google maps tutorial" on google search.

!