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
- 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.
- 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:
1 2 3 |
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.
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.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.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 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.
1 2 3 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
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 = "https://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.
1 2 3 |
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:
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