ZionSoft     About     Archive     Feed     Privacy

Play with Google Play Services 3 - Map

If you haven’t set up Google Play services yet, please follow this tutorial.

Get Maps API Key

First, create a project for your app in Google Developers Console, and enable Google Maps Android API v2.

Then get you the signing certificate’s fingerprint:

# displays fingerprint of your debug certificate
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
# displays fingerprint of your release certificate
keytool -list -keystore <your keystore>

Then use the SHA-1 fingerprint and your app’s package name to generate a new key for API access from Google Developers Console.

Update AndroidManifest.xml

Now update your app’s AndroidManifest.xml file, specifying the permissions, feature required, and the map key:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>

Add a Map

The easiest way to show a map is to add a MapFragment (or a SupportMapFragment for older devices) to your activity. Another approach is to add a MapView to your activity or fragment.

To add a map view showing satellite maps with an XML file:

<?xml version="1.0" encoding="utf-8"?>
        map:mapType="satellite" />

Then in your activity:

public class MainActivity extends Activity {
    private MapView mMapView;
    protected void onCreate(Bundle savedInstanceState) {
        // if you use a map fragment, it will take care of its life-cycle management
        // if you use a map view, you need to forward all the following events to it
        mMapView = (MapView) findViewById(R.id.map_view);
    protected void onResume() {
    protected void onPause() {
    protected void onDestroy() {
    protected void onSaveInstanceState(Bundle outState) {
    public void onLowMemory() {

GoogleMap Object

Once you have the map ready, you can use the getMap() method (or the getMapAsync() to get reference to the map asynchronously) of the map view or fragment to get a GoogleMap object. If this method returns null, it means the map is not ready yet (e.g. because the Google Play services is not available). It serves as the entry point for interactions with the map:

  • To configure the UI, e.g. show / hide my location button, enable / disable gestures, use the UiSettings object fetched using GoogleMap.getUiSettings() method.
  • To convert between coordinates on the map and the location on the screen, use the Projection object fetched using GoogleMap.getProjection() method.
  • You can uses GoogleMap.setMyLocationEnabled() method to show or hide the blue dot representing device’s current location, but to get the current location you should follow my previous tutorial on locations.
  • To listen to map click events, you can simply set the corresponding listener using GoogleMap.setOnMapClickListener() or GoogleMap.setOnMapLongClickListener() method.
  • You can set the camera (i.e. which part of the map should be shown) using the GoogleMap.animateCamera() (with animation) or GoogleMap.moveCamera() (no animation) method. To listener to camera changes (e.g. triggered by user), you can specify the corresponding listener using GoogleMap.setOnCameraChangeListener().

Also, you can set map types (normal, satellite, etc.), enable / disable indoor maps, 3D buildings, etc. using the GoogleMap object.

Markers and Info Windows

Markers can be used to indicate locations or other important information on the map, with more detailed information shown in the info window.

The following snippet adds a marker with a custom icon to the map, and displays a default info window showing “Hello, Helsinki!”:

protected void onResume() {
    mGoogleMap = mMapView.getMap();
    BitmapDescriptor bitmap = ...
    Marker addedMarker = mGoogleMap.addMarker(new MarkerOptions()
        .position(new LatLng(60.1708, 24.9375))
        .title("Hello, Helsinki")

One thing to note when using e.g. BitmapDescriptorFactory is, you might need to use MapsInitializer to explicitly initialize the map.

To remove a marker, you can use the Marker.remove() method, or the GoogleMap.clear() method to remove all added markers, shapes, etc.

If you want to animate a marker on the map (e.g. use a custom marker to indicate current location instead of the boring blue dot), all you need is simply update its position periodically using the Marker.setPosition() method.

When the user clicks on a marker, by default it shows an info window with some title and snippet defined when the marker was added. But you can also listen to the click event:

mGoogleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
    public boolean onMarkerClick(Marker marker) {

If the onMarkerClick() method returns true, it means the click event has been consumed. Otherwise, if false is returned, it will execute the default behavior, i.e. moving the camera to the marker, and showing the info window.

To provide a customized info window:

mGoogleMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
    public View getInfoWindow(Marker marker) {
        // this will be first called
        // the returned view will be used as the entire info window
    public View getInfoContents(Marker marker) {
        // this will only be called if getInfoWindow() returns null
        // the returned view will be used inside the default info window frame

The info window is rendered as an image. It means any subsequent changes won’t be visible unless you re-open the info window, and the info window can only listen to one click event for the whole info window.

Circles, Polygons, and Polylines

To add those shapes to the map, you basically follow the same pattern:

Circle addedCircle = mGoogleMap.addCircle(new CircleOptions()
    .center(new LatLng(60.1708, 24.9375))
// when adding a polygon, the system will automatically connect the
// last coordinate to the first one
Polygon addedPolygon = mGoogleMap.addPolygon(new PolygonOptions()
    .add(new LatLng(60, 24), new LatLng(61, 24), new LatLng(61, 25), new LatLng(60, 25));
// the system won't automatically connect the coordinates
// thus you can see the difference compared to the above polygon
Polyline addedPolyline = mGoogleMap.addPolyline(new PolylineOptions()
    .add(new LatLng(60, 24), new LatLng(61, 24), new LatLng(61, 25), new LatLng(60, 25));

Ground and Tile Overlays

The main difference between these two overlays is: the ground overlay provides a single image for a fixed location on the map, while the tile overlay provides a set of images for different locations at different zoom level on the map.

To add a ground overlay:

GroundOverlay addedGroundOverlay = mGoogleMap.addGroundOverlay(new GroundOverlayOptions()
    .anchor(0.5, 0.5)
    .position(new LatLng(60.1708, 24.9375), 100, 100));

To add a tile overlay:

TileProvider tileProvider = new TileProvider() {
    public Tile getTile (int x, int y, int zoom) {
        // a Tile object consists of raw image data, as well its width and height
        // the map is divided into a 2^zoom x 2^zoom grid
        // for each grid, the system targets 256 x 256 dp
        // if TileProvider.NO_TILE is returned,
        // it means you don't want to provide tiles yourself
        // if null is returned, it means the tile could not be found now,
        // and will be tried again later
TileOverlay addedTileOverlay = mGoogleMap.addTileOverlay(new TileOverlayOptions()

That’s it for today. Happy hacking and keep reading :)