Sunday, May 25, 2014

Integrating Google Maps API into your Mobile Application



I get a lot of students asking me, "how do I use Google Maps API in my Android Application?"  The answer is not incredibly straight forward, there are many preliminary steps that must be taken in order to complete the integration.

The Google Maps API can be found within the Google Play Services Library.   So first, you must download and install Google Play Services which can be found in the Android SDK Manager within the Extras folder.


Next, import the google-play-services _lib to your project as a library.  This can be easily done in Eclipse by navigating to File>Import then clicking on Android>Existing Android Code Into Workspace.



On the next screen press Browse.. Then browse for the google play services library by navigating to  your Android SDK folder>extras>google>google_play_services>libproject>google-play-services_lib, check Copy projects into workspace, then press Finish to import the project. 


Add the google play services library to your project by right clicking on the project, then going to properties.  From there, navigate to Android, then press the Add… button, and add google-play-services_lib to your project library.


To use Google Maps API, Google requires all projects to generate an SHA-1 fingerprint and register it on the Google Console so that developers can generate an Android Google Maps API key for use in their project.  To do this, you must install and access Keytool.  This is also made simple for Eclipse users, by navigating to Help>Install New Software.. From here press the Add button and under Location in the Add Repository window type in the URL of the Keytool download http://keytool.sourceforge.net/update then press Okay. 



From here just check Keytool, then press Next.  You will prompted to agree to the terms and conditions, so read all the terms and press agree if you agree to the terms of the license agreement.  Once the update is installed you will need to restart your IDE in order for the Keytool to be fully integrated into Eclipse.


Once Eclipse is restarted you should notice that Keytool now appears in your top menu bar.  This will now allow you to find your SHA-1 fingerprint, to do so you will need to navigate to Keytool>Open keystore.  Then Browse for debug.keytool which is located in your Username>.android>debug.keystore.  Input the password for debug.keystore, by default the password is “android”, then press Load.



You should notice that at the bottom menu of your screen a new tab called Keytool appears, and an android debug key is toggleable.  Double click on androiddebugkey and you will be prompted with a certificate which clearly labels your SHA-1 Fingerprint.


Copy your SHA-1 finger print then open up your web browser to access the Google API Console at http://code.google.com/apis/console .  From here, navigate to Services and toggle Google Maps Android API v2 on.


Then jump to API Access and select Create new Android key…  In this window paste your SHA-1 Fingerprint followed by your package as instructed at the button of the window then press Create.


You will now be able to see an API key that is generated with your Android App information with the Google APIs Console.  This is important since you will need it when accessing Google Maps API within your project.  Copy this API Key and save it for later use.
Now that we have everything we need, we can finally start coding! 
Open your IDE back up and navigate to your AnroidManifest.xml file and open it.  You will need to add some meta-data to your xml which includes the Google Play Services version and the Google Maps API key.  Paste this xml code just after the end of your activity in AndroidManifest.xml. 
<meta-data
              android:name="com.google.android.gms.version"
              android:value="@integer/google_play_services_version" />
<meta-data
     android:name="com.google.android.maps.v2.API_KEY"
     android:value="AIzaSyCUGhTZ37KsBrfELupNr8kPhLaYBufnB1Q" />
Be sure to replace my android:value with the API key that you copied from the Google APIs Console. 
Google Maps also needs a series of permissions ACCESS_NETWORK_STATE which checks the network state to see if data can be downloaded; INTERNET which checks for an internet connection; WRITE_EXTERNAL_STORAGE to allow Google Maps to store data in an external storage device; ACCESS_COARSE_LOCATION which finds the user’s location through WiFi and cell data; ACCESS_FINE_LOCATION which finds a user’s location through GPS; OpenGL ES V2 which allows for OpenGL ES v2 graphics which Google Maps uses.
Paste these permissions in your code just before the application starts.

<permission
        android:name="com.example.googlemapstest.permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />

    <uses-permission android:name="com.example.googlemapstest.permission.MAPS_RECEIVE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />   
Replace any calling to my package name with your package name.  After these permissions, also include a uses-feature which enables OpenGL ES v2.
<uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />
The general structure of your Android Manifest should look like this.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.googlemapstest"
    android:versionCode="1"
    android:versionName="1.0" >
   
    <uses-sdk
        android:minSdkVersion="12"
        android:targetSdkVersion="19" />

    <permission
        android:name="com.example.googlemapstest.permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />

    <uses-permission android:name="com.example.googlemapstest.permission.MAPS_RECEIVE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
   
    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name">
        <activity
            android:name="com.example.googlemapstest.MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppBaseTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
       
        <meta-data
              android:name="com.google.android.gms.version"
              android:value="@integer/google_play_services_version" />
      
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="AIzaSyCUGhTZ37KsBrfELupNr8kPhLaYBufnB1Q" />
    </application>

</manifest>
From here, you can now navigate to your main layout (activity_main.xml or whichever layout you are using to display your maps).   If you want your map to take up your entire screen replace your Layout and text with a new relative layout that fills the height/width of your screen.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
</RelativeLayout>

Within your relative layout, insert a fragment which will display a Google Map.
<fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.google.android.gms.maps.MapFragment"/>
You can now program a Google Map display as a map fragment.  Navigate to the activity class that you are planning to display the Google Map on.  If you are familiar with displaying content from the Res folder on screen, the process is very similar.  You will need to set a google map equal to a map fragment.  So create a GoogleMap field.
private GoogleMap map;
 After the setContentView of your main layout, set the field equal to the map fragment.
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
 Upon building you should be able to see a map of the world through Google Maps API on your screen.
The last thing we will want to do is add a marker.  In this example, we will mark the greatest city in the world, Chicago, Illinois.  First we will find the latitude and longitude of Chicago and input it in a field.
static final LatLng chicago = new LatLng(41.8819, -87.6278);
Next, within the onCreate method, we will add a Marker and give it the position and title of our Latlng.
Marker chicagoMarker = map.addMarker(new MarkerOptions().position(chicago).title("Chicago"));
The general structure of your Activity class should look like this.
public class MainActivity extends ActionBarActivity {

         static final LatLng chicago = new LatLng(41.8819, -87.6278);
         private GoogleMap map;

         @Override
         protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
           map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap(); 
           Marker chicagoMarker = map.addMarker(new MarkerOptions().position(chicago).title("Chicago"));
         }
}

Test your build, and you should see a map of the world with a maker on Chicago.


No comments:

Post a Comment