Google Static Maps Android

Filed Under: Android

In this tutorial we’re going to implement a google static maps in our android application. Google Static Maps API typically shows fewer points of interest compared to Google Maps.

Google Static Maps

  1. Google Static Maps API allow us to dynamically create a map image based on URL parameters (i.e. latitude, longitude, zoom level, encoded polyline etc.) sent through a standard HTTP request. When called, it returns the map as an image allowing developers to display it on the user interface.
  2. Google Static Maps API returns an image (either GIF, PNG or JPEG) in response to an HTTP request via a URL. For each request, we can specify the location of the map, the size of the image, the zoom level, the type of map, and the placement of optional markers at locations on the map. We can additionally label your markers using some standard alphanumeric characters.

A Google Static Map must be of the form:


https://maps.googleapis.com/maps/api/staticmap?parameters

The parameters of the url must be properly URL encoded before the http request is sent.

Google Static Maps parameters

Some required parameters for google static maps are described below.

  1. center: This defines the center of the map, equidistant from all edges of the map. This parameter takes a location as either a comma-separated {latitude, longitude} pair (e.g. “40.714728,-73.998672”) or a string address (e.g. “city hall, new york, ny”) identifying a unique location on the face of the earth.
  2. zoom: This defines the zoom level of the map, which determines the magnification level of the map. This parameter takes a numerical value corresponding to the zoom level of the region desired.
  3. size: This defines the rectangular dimensions of the map image. This parameter takes a string of the form {horizontal_value}x{vertical_value}. For example, 500×400 defines a map 500 pixels wide by 400 pixels high.

Several other parameters like markers and path take multiple locations. In those cases, the locations are separated by the pipe (|) character.

Google Static Maps Android Application

Let’s create an application that returns a google static map image and display it in a circular ImageView.

Below image shows the android studio project structure.

google static maps android project

Google Static Maps Android Code

In this tutorial we’ve used a third party library to create a CircularImageView. We recommend using and integrating third party libraries wherever feasible as it saves time in writing some standard custom classes that are pretty common.


compile 'com.pkmmte.view:circularimageview:1.1'

To send and receive the http url and response you need to add a few jar files in the project.

  • httpclient-4.3.3.jar
  • httpcore-4.3.3.jar
  • httpmime-4.3.3.jar

Sync the gradle dependencies to add the libraries in the project. On running this project now a DuplicateFileExpection might arise in the build.gradle. It’s due to conflicting package files of the libraries. A workaround is adding the following in the android tag of the build.gradle file.


packagingOptions {
        exclude 'META-INF/DEPENDENCIES.txt'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/dependencies.txt'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/LGPL2.1'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/notice.txt'
    }

The content_main.xml is defined as below.


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:background="@android:color/black"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.journaldev.staticmaps.MainActivity"
    tools:showIn="@layout/activity_main">

    <com.pkmmte.view.CircularImageView
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:clickable="true"
        android:id="@+id/img_map_route"
        android:layout_gravity="center"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />


</RelativeLayout>

The MainActivity.java looks like below.


package com.journaldev.staticmaps;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;

import com.pkmmte.view.CircularImageView;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public class MainActivity extends AppCompatActivity {

    private String STATIC_MAP_API_ENDPOINT = "http://maps.googleapis.com/maps/api/staticmap?size=230x200&path=";
    String path;


    CircularImageView iv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        iv=(CircularImageView)findViewById(R.id.img_map_route);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        try {

            String marker_me = "color:orange|label:1|Brisbane";
            String marker_dest = "color:orange|label:7|San Francisco,USA";
            marker_me = URLEncoder.encode(marker_me, "UTF-8");

            marker_dest = URLEncoder.encode(marker_dest, "UTF-8");
            path = "weight:3|color:blue|geodesic:true|Brisbane,Australia|Hong Kong|Moscow,Russia|London,UK|Reyjavik,Iceland|New York,USA|San Francisco,USA";
            path = URLEncoder.encode(path, "UTF-8");

            STATIC_MAP_API_ENDPOINT = STATIC_MAP_API_ENDPOINT + path + "&markers=" + marker_me + "&markers=" + marker_dest;

            Log.d("STATICMAPS", STATIC_MAP_API_ENDPOINT);

            AsyncTask<Void, Void, Bitmap> setImageFromUrl = new AsyncTask<Void, Void, Bitmap>(){
                @Override
                protected Bitmap doInBackground(Void... params) {
                    Bitmap bmp = null;
                    HttpClient httpclient = new DefaultHttpClient();
                    HttpGet request = new HttpGet(STATIC_MAP_API_ENDPOINT);

                    InputStream in = null;
                    try {
                        HttpResponse response = httpclient.execute(request);
                        in = response.getEntity().getContent();
                        bmp = BitmapFactory.decodeStream(in);
                        in.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return bmp;
                }
                protected void onPostExecute(Bitmap bmp) {
                    if (bmp!=null) {

                        iv.setImageBitmap(bmp);

                    }

                }
            };

            setImageFromUrl.execute();

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

In the above code we’ve url encoded the markers parameters and path parameters using URLEncoder.encode(path, "UTF-8");.

This makes the string url compatible by removing the white spaces and replacing them by %20C etc.

An AsyncTask anonymous inner class is created that sends the encoded static map api url using http call and the response returned is the Bitmap static map image of the url.
That bitmap is loaded into the CircularImageView. The following snippet is used to decode the Bitmap from the response stream.


bmp = BitmapFactory.decodeStream(in);

In this example we’ve set two markers and a path consisting of some prominent landmarks across the globe. For many points along the path we can pass an encoded polyline string too. This will be discussed in a later tutorial.

The output of the application is given below:
android google static map

This brings an end to google static maps android application tutorial. You can download the final Android StaticMaps Project from the link below.

Reference: Official Documentation

Comments

  1. Josi says:

    Google won’t allow a request without API key anymore. You need to append google static map API key to your url in order to get the image.

  2. gaurav Meghanthi says:

    i want to change App Theme color on this string String marker_me = “color:orange|label:1|Brisbane”;
    like one String Maker_me =”color:”+ContextCompact().getcolor(R.color.color_primary)+”|label:1|Brisbane”; is it possible or not..? just tell me what ever your answer

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages