Mobile applications are becoming as popular as mobile websites and traditional websites; thus, adding a mapping solution to your business’ mobile applications is just as important as it is for your websites. This is particularly pertinent if you are a business with multiple store locations or if you would like to display search results within a certain geographic area. When developing applications for Android devices, the Google Maps Android API v2 is the standard API for implementing mapping solutions and it comes with no fees (See terms of service here). After following a few important setup procedures, the basic implementation is quite easy. Assuming the reader has some knowledge in creating projects in the Eclipse IDE and has already created a base project for this demo, I’m going to proceed with explaining the setup.
Setup Google Maps Android API v2
First, the Google Maps Android API v2 is distributed within the Google Play Services SDK and is available to developers within the Android SDK Manager. You can open the manager by finding and clicking the Android SDK Manager icon in Eclipse. Once the Google Play Services SDK has been downloaded, you will need to add it to your Eclipse workspace. Click File -> New -> Other -> Android Project from Existing Code and then Next. For the Root directory, click Browse, and then navigate to the sdkextrasgooglegoogle_play_serviceslibproject folder within your Android SDK folder. Click the google-play-services_lib project as well as the “Copy projects into workspace” checkbox. Click Finish. Then, within your project, add a reference to the google-play-services_lib.
Next, unlike traditional websites, in order to implement Google mapping, mobile applications require a Maps API key that is obtained by registering the project in the Google APIs Console. The API key is linked to the application’s certificate, so you can either use the debug certificate or generate a production certificate by signing your application. Instructions can be found here. Once you’ve determined which certificate to use, obtain the SHA-1 fingerprint for the certificate by using KeyTool.
Debug:
keytool -list -v -keystore "C:Usersyour_user_name.androiddebug.keystore" -alias androiddebugkey -storepass android -keypass android
Production: keytool -list -v -keystore your_keystore_name -alias your_alias_name
Next, navigate to the Google APIs Console and click the API Access link. In the next page, click the Create New Android Key button. You will be prompted to enter the SHA-1 fingerprint from your application’s certificate, then a semicolon, then your application’s package name; for example:
BB:0D:AC:74:D3:21:E1:43:67:71:9B:62:91:AF:A1:66:6E:44:5D:75;com.seguetech.mapexample
The Google APIs Console then displays a forty-character API key that you must add to your project’s Application Manifest within the element.
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="your_api_key"/>
Keep the Application Manifest open because we also need to set some permissions and “uses feature” elements so that the application can access Android system features and the Google Maps servers. You will also need to determine if your application will utilize the device’s Location Services. Here are the permissions you must add within the manifest element of the Application Manifest:
Finally, Google Maps Android API v2 requires OpenGL ES version 2, a graphics programming interface. It is available on 90% of Android devices, but in order to prohibit the incompatible devices from downloading your application from the Google Play Store, you need to add a uses-feature element within the manifest element.
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
That’s it. Setup is complete-now onto actually coding the map’s functionality within an activity.
Programming Google Maps Android API v2
There are two types of sub-classes we can utilize in order to implement Google Mapping. Each acts as a container for the map and provides access to the GoogleMap object. The MapFragment object is used to place a map within an Android Fragment, so that you can reuse the Fragment across multiple activities. One caveat is that the MapFragment requires APL level 12 or higher, so if you intend to support earlier APIs, the same functionality is available through the SupportMapFragment. The second sub-class is the MapView, which allows developers to put a map in an Android View. This object requires forwarded life cycle methods from the Activity to the corresponding methods in the MapView class. Thus, the MapFragment is simpler to implement and will be used in this example.
First, we need to create our layout map fragment. Within the reslayout folder, create a map.xml file and add the following code. We will be referencing the MapFragment object from the API.
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.MapFragment"/>
Then, within your activity class (remember to add the activity to the Manifest), set the map.xml as your content view (setContentView(R.layout.map;) and declare a private instance of the Google Map object (private GoogleMap map;). You can now manipulate the map object in a similar way as with traditional websites. Set the map object to the MapFragment in the layout file:
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))
.getMap();
Now, add some markers. The attached image shows the four locations for our Lost Dog Cafe mobile application. For each marker, simply call the addMarker method and pass in a MarkerOptions object which includes the latitude and longitude geocode as well as a title, a snippet, and an icon. The snippet is the text that is displayed in the info.Window, which can be attached to an onInfoWindowClick listener. In this example, the marker’s icon is set to a variable defined in our drawable resources and the onInfoWindowClick method opens a new activity using an Intent. I’ve displayed many of the properties of the Marker object with which you can provide the new activity.
map.addMarker(new MarkerOptions().position(new LatLng(39.233956, -77.484703))
.title("This is the title")
.snippet("This is the snippet within the InfoWindow")
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.icon)));@Override
public void onInfoWindowClick(Marker marker) {
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra(”snippet”, marker.getSnippet());
intent.putExtra(”title”, marker.getTitle());
intent.putExtra(”position”, marker.getPosition());
startActivity(intent);
}
There are also other layers and buttons which can be configured for the map. The traffic layer can be enabled as well as the location refresh by adding the following two lines of code:
map.setTrafficEnabled(true);
map.setMyLocationEnabled(true)
That’s it! Now you have a fully functional Google mapping solution for Android devices.
Final Activity Code
package com.sample.activities;
import com.sample.R;
import com.sample.NewActivity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
public class MapActivity extends Activity implements OnInfoWindowClickListener {
private LatLng defaultLatLng = new LatLng(39.233956, -77.484703);
private GoogleMap map;
private int zoomLevel = 7;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map);
try {
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))
.getMap();
if (map!=null){
map.getUiSettings().setCompassEnabled(true);
map.setTrafficEnabled(true);
map.setMyLocationEnabled(true);
// Move the camera instantly to defaultLatLng.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(defaultLatLng, zoomLevel));
map.addMarker(new MarkerOptions().position(defaultLatLng)
.title("This is the title")
.snippet("This is the snippet within the InfoWindow")
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.icon)));
map.setOnInfoWindowClickListener(this);
}
}catch (NullPointerException e) {
e.printStackTrace();
}
}
@Override
public void onPause() {
if (map != null){
map.setMyLocationEnabled(false);
map.setTrafficEnabled(false);
}
super.onPause();
}
@Override
public void onInfoWindowClick(Marker marker) {
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("snippet", marker.getSnippet());
intent.putExtra("title", marker.getTitle());
intent.putExtra("position", marker.getPosition());
startActivity(intent);
}
}
This post was originally published on 07/01/2013
August 2015 Update
Over the two years since this post was published, the Google Maps Android API v2 has remained relatively constant. It is still distributed with the Google Play Services library and still requires little effort to implement. What has changed is the widespread replacement of Eclipse with Android Studio as the IDE of choice for Android mobile developers. Fortunately these setup instructions work with Android Studio with the following minor exceptions:
In the Dependencies section of the build.gradle file, the following two libraries must be referenced:
compile 'com.google.android.gms:play-services:7.5.0'
compile 'com.android.support:support-v4:22.2.0'
Upgrading to the latest Google Play Services library (7.5.0) requires just two changes to the MapActivity code above:
1. In the import section, replace import com.google.android.gms.maps.MapFragment; with import com.google.android.gms.maps.SupportMapFragment;In the onCreate method replace In the onCreate method replace
2. In the onCreate method replace
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)) )).getMap();
with
map = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id. map)).getMap();