Skip to main content

Android: Google Map V2

1. Downloading Google Play Services

Google made new Maps V2 API as a part of Google Play Services SDK. So before we start developing maps we need to download google play services from SDK manger. You can open SDK manager either from Eclipse or from android sdk folder.
Open Eclipse ⇒ Windows ⇒ Android SDK Manager and check whether you have already downloaded Google Play Services or not under Extras section. If not select play services and install the package.


 2. Importing Google Play Services into Eclipse

After downloading play services we need to import it to Eclipse which will be used as a library for our maps project.
1. In Eclipse goto File ⇒ Import ⇒ Android ⇒ Existing Android Code Into Workspace
2. Click on Browse and select Google Play Services project from your android sdk folder. You can locate play services library project from
android-sdk-windows\extras\google\google_play_services\libproject\google-play-services_lib
3. Importantly while importing check Copy projects into workspace option as shown in the below image.


3. Getting the Google Maps API key

1. Same as in maps v1 we need to generate SHA-1 fingerprint using java keytool. Open your terminal and execute the following command to generate SHA-1 fingerprint.

On Windows
keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
On Linux or Mac OS
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
In the output you can see SHA 1 finger print.
 

2. Now open Google API Console
3. Select Services on left side and turn on Google Maps Android API v2



4. Now select API Access on left side and on the right side click on Create new Android key…


 And note down the API key which required later in our project.


4. Creating new Project

After completing required configuration, It’s time to start our project.
1. In Eclipse create a new project by going to File ⇒ New ⇒ Android Application Project and fill required details. I kept my project name as Google Maps V2 and package name as info.androidhive.info
2. Now we need to use Google Play Services project as a library to use project. So right click on project and select properties. In the properties window on left side select Android. On the right you can see a Add button under library section. Click it and select google play services project which we imported previously.



3. Add the Map Key in the manifest file. Open AndroidManifest.xml file and add the following code before tag. Replace the android:value with your map key which you got from google console.

<!-- Goolge Maps API Key -->
<meta-data
     android:name="com.google.android.maps.v2.API_KEY"
     android:value="Youe API KEY" />
4. Google maps needs following permissions and features.

ACCESS_NETWORK_STATE – To check network state whether data can be downloaded or not
INTERNET – To check internet connection status
WRITE_EXTERNAL_STORAGE – To write to external storage as google maps store map data in external storage
ACCESS_COARSE_LOCATION – To determine user’s location using WiFi and mobile cell data
ACCESS_FINE_LOCATION – To determine user’s location using GPS
OpenGL ES V2 – Required for Google Maps V2

Finally my AndroidManifest.xml file looks like this (Replace the package name with your project package)

AndroidManifest.xml
 
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.androidhive.googlemapsv2"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <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-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <!-- Required OpenGL ES 2.0. for Maps V2 -->
    <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="info.androidhive.googlemapsv2.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>
        <!-- Goolge API Key -->
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="AIzaSyBZMlkOv4sj-M5JO9p6wksdax4TEjDVLgo" />
    </application>
</manifest>
5. New google maps are implemented using MapFragments which is a sub class of Fragments class. Open your main activity layout file activity_main.xml file and add following code. I used RelativeLayout as a parent element. You can remove it and use MapFragment directly.

activity_main.xml
 
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>
6. Add the following code in your Main Activity java (MainActivity.java) class.

MainActivity.java
 
public class MainActivity extends Activity {
    // Google Map
    private GoogleMap googleMap;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            // Loading map
            initilizeMap();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * function to load map. If map is not created it will create it for you
     * */
    private void initilizeMap() {
        if (googleMap == null) {
            googleMap = ((MapFragment) getFragmentManager().findFragmentById(
                    R.id.map)).getMap();
            // check if map is created successfully or not
            if (googleMap == null) {
                Toast.makeText(getApplicationContext(),
                        "Sorry! unable to create maps", Toast.LENGTH_SHORT)
                        .show();
            }
        }
    }
    @Override
    protected void onResume() {
        super.onResume();
        initilizeMap();
    }
 }
Some Useful Tips:

As you know,the new Google Maps API v2 released in Dec,2012.
Accordingly, the method to Display Google Map on Android very differs from that of the past(Google Maps API v1). But many people are not likely to realize this differences from now on.
First of all
to set the Google Service Library, the Support Library, and the valid API key is required in advance. If you know HOT to do it, please read this two documents carefully: One and Two.
Second
the code to display the ordinary Google Map also differs from that of MapView which has been known since the past(Google Maps API v1).
I introduce the second issue to the new Android developers in the self-answered form as follows;
1. Display the ordinary Google Map in (Support)Fragment.
main.xml...
Note that "class="com.google.android.gms.maps.SupportMapFragment"" is correct.
The old version used "class="com.google.android.maps.SupportMapFragment""

<?xml version="1.0" encoding="utf-8"?>
<!-- This can go anywhere in your layout (see other demos for some examples). -->
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/map"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  class="com.google.android.gms.maps.SupportMapFragment"/>
 
MainActivity.java.... Note that all classes to be imported in the MainActivity must be like below; Please check if the imported classes have com.google.android.gms.maps.xxxxxxx type.

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import android.os.Bundle;

/**
 * This shows how to create a simple activity with a map and a marker on the map.
 * <p>
 * Notice how we deal with the possibility that the Google Play services APK is not
 * installed/enabled/updated on a user's device.
 */
public class BasicMapActivity extends android.support.v4.app.FragmentActivity {
    /**
     * Note that this may be null if the Google Play services APK is not available.
     */
    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setUpMapIfNeeded();
    }

    @Override
    protected void onResume() {
        super.onResume();
        setUpMapIfNeeded();
    }

    /**
     * Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly
     * installed) and the map has not already been instantiated.. This will ensure that we only ever
     * call {@link #setUpMap()} once when {@link #mMap} is not null.
     * <p>
     * If it isn't installed {@link SupportMapFragment} (and
     * {@link com.google.android.gms.maps.MapView
     * MapView}) will show a prompt for the user to install/update the Google Play services APK on
     * their device.
     * <p>
     * A user can return to this Activity after following the prompt and correctly
     * installing/updating/enabling the Google Play services. Since the Activity may not have been
     * completely destroyed during this process (it is likely that it would only be stopped or
     * paused), {@link #onCreate(Bundle)} may not be called again so we should call this method in
     * {@link #onResume()} to guarantee that it will be called.
     */
    private void setUpMapIfNeeded() {
        // Do a null check to confirm that we have not already instantiated the map.
        if (mMap == null) {
            // Try to obtain the map from the SupportMapFragment.
            mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                    .getMap();
            // Check if we were successful in obtaining the map.
            if (mMap != null) {
                setUpMap();
            }
        }
    }

    /**
     * This is where we can add markers or lines, add listeners or move the camera. In this case, we
     * just add a marker near Africa.
     * <p>
     * This should only be called once and when we are sure that {@link #mMap} is not null.
     */
    private void setUpMap() {
        mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
    }
}
 
2. Display MapView in (Support)Fragment.
main.xml....
Note that "class="com.google.android.gms.maps.MapView"" is correct.
The old version used "class="com.google.android.maps.MapView".

<?xml version="1.0" encoding="utf-8"?>
<!-- This can go anywhere in your layout. -->
<com.google.android.gms.maps.MapView xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/map"
  android:layout_width="match_parent"
  android:layout_height="match_parent"/>
 
MainActivity.java...
Note that all classes to be imported in the MainActivity must be like below; Please check if the imported classes have com.google.android.gms.maps.xxxxxxx type.
And you must add "mMapView.onCreate(savedInstanceState);" under OnCreate().

import android.os.Bundle;
import com.google.android.gms.maps.MapView;

/**
 * This shows how to create a simple activity with a raw MapView and add a marker to it. This
 * requires forwarding all the important lifecycle methods onto MapView.
 */
public class RawMapViewDemoActivity extends android.support.v4.app.FragmentActivity {
    private MapView mMapView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mMapView = (MapView) findViewById(R.id.map);
        mMapView.onCreate(savedInstanceState);

    }

    @Override
    protected void onResume() {
        super.onResume();
        mMapView.onResume();

    }

    @Override
    protected void onPause() {
        mMapView.onPause();
        super.onPause();
    }
    @Override
    protected void onDestroy() {
        mMapView.onDestroy();
        super.onDestroy();
    }
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mMapView.onLowMemory();
    }
}
 
Specially, in case of MapView, many people make a mistake that after setting "com.google.android.maps.MapView.." in their main.xml, they import the "com.google.android.gms.maps.MapView" in their MainActivity. It causes the ANR(error). In the reverse case is the same result.
Therefore, always check if the same class or object must be used or imported in both main.xml and MainActivity.java of your app.

Comments

  1. I simply want to say I’m very new to blogs and actually loved you’re blog site. Almost certainly I’m going to bookmark your blog post . You absolutely come with great well written articles. Thanks a lot for sharing your blog.

    Android training in chennai with placement | Android Training in chennai |Android Training in Velachery

    ReplyDelete
  2. Thanks a lot! You made a new blog entry to answer my question; I really appreciate your time and effort.

    Android Training in chennai | Android Training|Android Training in chennai with placement | Android Training in velachery

    ReplyDelete

Post a Comment

Popular posts from this blog

Fragment: App loads with white screen for 3 secs before showing proper UI

Issue: 1) When my application start then white/black screen appears, and then main UI is display.  2) Before my fragment load in activity black/white screen appears for 3/4 seconds and then fragment load. Solution: To fix this nasty problem, update the /res/values/styles.xml to include <item name="android:windowDisablePreview">true</item> or <item name="android:windowBackground">@android:color/black</item> for example : <!-- Application theme. -->  <style name="AppTheme" parent="AppBaseTheme">  <!-- All customizations that are NOT specific to a particular API-level can go here. -->  <item name="android:windowDisablePreview">true</item>  <!-- <item name="android:windowBackground">@android:color/black</item> -->  </style>

Android: The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files

Solution Try the following any one solution and problem will go away: 1)  Apply following steps: Close the project and reopen it. Clean the project (It will rebuild the buildpath hence reconfiguring with the JDK libraries) OR Delete and Re-import the project and if necessary do the above steps again. 2)  Apply following steps: Go to properties of project with the build error (right click > Properties) View the "Libraries" tab in the "Build Path" section Find the "JRE System Library" in the list (if this is missing then this error message is not an eclipse bug but a mis-configured project) Remove the "JRE System Library" Hit "Add Library ...", Select "JRE System Library" and add the appropriate JRE for the project (eg. 'Workspace default JRE') Hit "Finish" in the library selection and "OK" in the project properties and then wait for the re-build of the project Hopefully th

Error: Retrieving parent for item: No resource found that matches the given name after upgrading to AppCompat v23

My project is going on easily but suddenly what I found below bugs when developing an app. I know it's minor bug but it may be useful to anyone. Here is the error: Error:(2) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Inverse'. Error:(2) Error retrieving parent for item: No resource found that matches the given name 'android:Widget.Material.Button.Colored'. Solution: This happens because after updates your android studio uses API 23 by default. 1) First check that your compile SDK version must match the support library's major version. If you are using version 23 of the support library, you need to compile against version 23 of the Android SDK. Alternatively you can continue compiling against version 22 of the Android SDK by switching to the latest support library v22.   2) Go to your project structure -> Properties -> and change Build tool version to