Google Maps

In this lecture, we learn how to incorporate Google Maps into applications - this is very cool. We have all used Google Maps on laptop browsers and smartphones but only as user up until now.

We will first learn how to create a map activity. Then through two simple demos apps we get a sense of the main programming features needed to construct and control maps. I even named a demo app after the city recently described by New York Times journalist Neil MacFarquhar as a "drab industrial city". Cheers Neil - I was born and brought up in the hip, bustling, vibrant town of Coventry. You clearly know "darb" when you see it Neil. I digress. Now we transition from one Android aka Neil to another.

What this lecture will teach you

Demo projects

We will use the i_am_here.zip app to demonstrate how to display a single map and update it as we move. This app can track you as you move around and put a marker on the map of your current location.

We also use the CoventryDemo.zip app which allows the user to interact with the map by placing markers on the map and then connecting up the markers with polylines drawn on the map. A polyline is a list of points, where line segments are drawn between consecutive points.

The Coventry demo is taken from here: detect MarkerClick and add Polyline The app detects long click on map and adds a marker. Lines can be drawn between markers using polylines.

These two apps will provide the necessary background to implement maps for MyRuns4.

Running the demo code

The new version of Android makes creating Google maps much easier than previous versions of the API. Just follow the two steps below to create Google Maps Activity and you are all set.

However, to get the existing demo code to run on your phone you need to follow the old way of creating maps. Here you need to (1) create Maps API key using Google Console; and (3) replace the existing Maps API key in the demo code’s google_maps_api.xml file (e.g., i_am_here or coventrydemo) with your new Maps API key. Sounds complicated but it is not. If you don’t do this and just run the demo code you will get errors such as 522-6622/edu.dartmouth.cs.iamhere E/Google Maps Android API﹕ Authorization failure. Note, you can create a Maps API key either in an unrestricted mode (which allows maps to run unrestricted in any of your apps)) or you can bind the key to a specific app using your SHA1 credentials; that is, you need to manually get a SHA1 fingerprint from your computer and bind it to the Maps API Key.;

Assuming you have created a new maps project in studio see [Step 3. Create a Google Maps project]https://developers.google.com/maps/documentation/android-api/start#display_your_apps_certificate_information) create your Maps API key by following Step 4. Get a Google Maps API key

As stated in Step 4 once you have generated a restricted or non restricted (I recommended non restricted; its faster and does not require you generating your SHA1) key you need to add your new key in the google_maps_api.xml fil. Note, you do not have to add this to the manifest file.

When you create a new MAP project Android Studio will open google_maps_api.xml file and show you short cuts to get the Map API key and then ask you to update the key - see YOUR_KEY_HERE below. Read the comments and XML before proceeding:

<resources>
<!--
TODO: Before you run your application, you need a Google Maps API key.
To get one, follow this link, follow the directions and press "Create" at the end:
https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&r=65:24:35:7B:14:72:FC:B7:35:EF:A9:2E:01:3D:EA:41:E9:67:40:A4%3Bedu.dartmouth.cs.mymaptest
You can also add your credentials to an existing key, using these values:
Package name:
65:24:35:7B:14:72:FC:B7:35:EF:A9:2E:01:3D:EA:41:E9:67:40:A4
SHA-1 certificate fingerprint:
65:24:35:7B:14:72:FC:B7:35:EF:A9:2E:01:3D:EA:41:E9:67:40:A4
Alternatively, follow the directions here:
https://developers.google.com/maps/documentation/android/start#get-key
Once you have your key (it starts with "AIza"), replace the "google_maps_key"
string in this file.
-->
<string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">YOUR_KEY_HERE</string>
</resources>

And when I get my Map Key API I update and run the app on my phone. It will get the map from Google and display it centered at Sydney OZ. Must of been an Aussie that coded this up, hey?

Creating Google Maps Activity

Above we explained how to run the demo code. But to create a new app from scratch it is a lot easier. Android Studio creates the SHA and key and you update the google_maps_api.xml

The overall process of adding a Google Map to an Android application is as follows -- note in this example set up I also show how to set up for a restricted key:

STEP 1: Add a Google Maps Activity to your project

As shown in figures below, you can either create a Google Maps Activity project from scratch (left) or add a Google Maps Activity (right) to your existing projects (e.g, MyRuns).

Have a first look of the generated MapsActivity. It extends itself from a FragmentActivity, containing a GoogleMap instance. It uses setUpMapIfNeeded() and setUpMap() to configure settings of the GoogleMap in this activity. Read through the comments for these two methods - we will extend the functionalities of them in the following samples and MyRuns4.

STEP 2: Obtain an API key for Google Maps v2.0

Go to google_maps_api.xml, you will find a generated url in the comments. This url is generated using the unique SHA-1 key of your current computer and the package name of the app. We also notice that there is a placeholder specifying the "google_maps_key". We need to get the key from the Google API Console and fill it in.

Copy this link to your browser and hit Enter, you will be directed to a page on the API console as shown below:

Hit "Continue" and "Create" to proceed. Wait a few seconds - your API key is being generated. Note that in the textbox your SHA-1 and package name are already there. You don't need to edit them at all.

Once the server is ready, you will be presented with the page like below. Copy the API Key back to the key placeholder in the xml file.

There are a number of meta-data and uses-permissions added to the Manifest file by Android Studio. Once you have the API key you added to google_maps_api.xml, you will find the meta-data for the api key in Manifest is updated as well (shown below). Now you are done with the setup for a Google Maps Activity.

I _Am_Here -- a tracking app

The first application we look at this is an extension of the applications we developed for the lecture on the LocationManger. As shown in the image below the app lists:

current longitude and latitude of your location

the address

and location on a map with a sickly green marker

The cool thing about this app is that as you move around it will update your position on the map. It tracks you. There is little control over the app. You can move the map around or use the simple zoon in / zoom out buttons on the map -- that is about it.

Let's discuss the code. Note, in the code examples below we snip some of the code that we have already discussed in the pervious lecture. You can look at the demo app source code to see the complete source code.

Much of the structure of the code is familiar now.

Set up Google Maps in onCreate()

The code first gets a reference to a GoogleMap using getSupportFragmentManager() on SupportMapFragment set up in layout/activity_main.xml, as shown below in the layout file

The getMap() method renders the Google Map returned from the server into the SupportMapFragment in layout. The type of map is then set to normal.

There are a number of types of maps that can be selected:

MAP_TYPE_HYBRID: Satellite maps with a transparent layer of major streets.

MAP_TYPE_NONE: No base map tiles.

MAP_TYPE_NORMAL: Basic maps.

MAP_TYPE_SATELLITE: Satellite maps with no labels.

MAP_TYPE_TERRAIN Terrain maps.

Change the type of the map in your code and look at the map rendered.

mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

After the map type is set we get the current location and set a marker at that location and zooms in. The location manager sets up the time and distance parameters as well as the call back listener for location updates:

Note, the above confiuration is an AND: give an update no faster than every 2 seconds AND only if the phone has moved 10 meters. If you want to see location updates every 2 seconds then set the distance parameter to zero. The sample code Log.d() every time onLocationChanged() is called. Check out the Logcat in Android Studio when you run the snippet with distance 0 set, as shown below.

User Tracking

Each time the callback onLocationChanged() is called the map is updated simply by calling the helper function discussed below. There is no action for the other callbacks in this code -- there really should be.

Coventry Demo

The Coventry app allows the user to interact with the map by placing markers on the map and then connecting up the markers with polylines drawn on the map. A polyline is a list of points, where line segments are drawn between consecutive points. The app detects long clicks on map and adds a marker. Lines can be drawn between markers using polylines. To do this the use clicks (do not long click) on a marker then moves to another marker and clicks. To remove the markers and lines click on the map.

In the image below the user has long clicked on three places on the map creating three markers. Then the user has clicked (just normal short click) on each point and the lines are drawn constructing a triangle around the vibrant metropolis of Coventry, England.

The logic for onMarkerClick() is straightforward. First time onMarkerClick() is called it will call new PolylineOptions().add(marker.getPosition()) to add the marker to the polyline. Next time it is called it will add the second marker --rectOptions.add(marker.getPosition()) -- and then draw the line. Each time a new marker is added (via a long click) and a line drawn -- the complete set of lines are redrawn starting at the first marker added to the rectOptions (i.e., the ployline). If the user clicks on the map (not the markers) and then clicks on any marker or does a long click to create a new marker then the line or polyline is remove - that is, the line between the markers is cleared.