
Creating our first map application
Creating our map application with Android Studio is very simple. Android Studio has inbuilt templates that help us to create our map application easily through some simple steps. The first method to do this is by editing the layout from the Android studio inbuilt template. Select File | New Project.
In the next screen, select the target Android SDK version and minimum Android SDK version that your application supports.
In the following screen, select activity as Google Maps Activity and select Next, as shown in the following image:

In the following screenshot, enter a name for activity and layout:

Finally, select Finish. Our map project will be created and all the permissions of the other components are added by default. Our job is to paste the API key to the google_maps_api.xml
file, which is present in the folder res/values
.
However, if you create an application in Eclipse, you need to add the permissions and other components manually and also configure Google Play services to get everything working. After configuring everything, let's proceed to the coding part, which is amazing.
Working with a layout
Add the following code to your main activity's layout file. The file is typically activity_main.xml
, but in my case, it is activity_maps.xml
:
<?xml version="1.0" encoding="utf-8"?> <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.google.android.gms.maps.MapFragment"/>
activity_maps.xml
This is the simplest way to load the map. The android:name
attribute in the preceding fragment specifies the MapFragment
class to instantiate the layout. The android:id
attribute defines a unique ID for our fragment.
Optional (for old APIs)
This code only works for API 12 or greater (that is, Honeycomb or later; it can also be called a modern API). To support lower versions of Android, such as Gingerbread, you need to use SupportMapFragment
.
To use SupportMapFragment
, replace the last line in the preceding fragment code with the following code:
android:name="com.google.android.gms.maps.SupportMapFragment"
Working with the Activity class
Now, let's proceed to the Activity
class. To get a basic map application running, we don't need anything special. Just link the activity to our main layout, which contains MapFragment
or SupportMapFragment
.
Use the following code in your main activity. For me, it is MapsActivity.java
:
package com.raj.map; import android.app.Activity; import android.os.Bundle; public class MapsActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); }}
MapsActivity.java
The first line of our code defines the package name of our project. Replace this with the package name you've created.
The next two lines import the Activity
and Bundle
classes, which are required essentially to run a basic Android application.
MapsActivity
is the name of our class, which is a subclass of the Activity
super class.
When our MapsActivity
is launched, the onCreate()
method is called first, which loads the layout defined in activity_maps.xml
.
Optional (for old APIs)
If you've used SupportMapFragment
instead of MapFragement
to support lower version devices, your MapsActivity
should extend to the FragmentActivity
class, which contains the support library to support lower versions of Android. You can download the support library from SDK Manager. If you are using Android Studio, you need to download the support repository.
Now, run your application in an Android emulator or a physical device. The basic application will work. For faster performance, it is better to use a physical device. You will get output similar to what is shown in the following screenshot:

Adding MapFragment programatically
In the last section, we added MapFragment
in our layout file directly. In this section, we are going to create MapFragment
dynamically in our activity. Open your main layout and enter the following code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
In the preceding code, we use FrameLayout
, which is used to display a single child view. Here, FrameLayout
is the child of LinearLayout
.
Next, we've defined content_frame
as the unique ID for the FrameLayout
.
Then, in our activity code, we will replace the contents of FrameLayout
with MapFragment
.
Use the following code in your main activity:
package com.raj.map; import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.os.Bundle; import com.google.android.gms.maps.MapFragment; public class MapsActivity extends Activity { Fragment mapFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); mapFragment = MapFragment.newInstance(); FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); fragmentTransaction.add(R.id.content_frame, mapFragment); fragmentTransaction.commit(); }}
MapsActivity.java
In the preceding code, mapFragment
is the object of the Fragment
class. The FragmentTransaction
class provides APIs to add, remove, and replace a fragment.
We create fragmentTransaction
as an object for the FragmentTransaction
class. Then, we use the add()
method to insert MapFragment
in FrameLayout
.
Finally, the commit()
method is called to apply the changes.
Optional – for older APIs
To support devices with API 11 or lower, we need to use the support library to provide compatibility.
Use the following code in your main activity:
package com.raj.map; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentTransaction; import com.google.android.gms.maps.SupportMapFragment; public class MapsActivity extends FragmentActivity { Fragment mapFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); mapFragment = SupportMapFragment.newInstance(); FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); fragmentTransaction.add(R.id.content_frame, mapFragment); fragmentTransaction.commit(); }}
MapsActivity.java
The preceding code provides the same functionality as the previous code. This code uses the SupportMapFragment
class instead of the MapFragment
class to support lower API devices.
When you notice the import
statement in the preceding code, you will see that the classes are imported from android.support.v4.app
.
The android.support.v4.app
package provides classes to support backward compatibility. Now you need not worry about backward compatibility problems that arise.
Next, run the code in the emulator or physical device; you will then see your app running.
In the next section, we are going to take a look at the GoogleMap
object.
Using the callback method
A callback function is a function you provide to another code, allowing it to be called by this code. The GoogleMap
object can be obtained from MapFragment
. You can get the GoogleMap
object directly, but it may return null sometimes, which makes the application likely to crash. So, a callback will handle this scenario seamlessly. To enable a callback on our MapFragment
, call the getMapAsync()
method on MapFragment
. Our activity must implement the OnMapReadyCallback
interface.
We must use the onMapReady()
method to handle the callback. Both getMapAsync()
and the callback will be called on the main thread. It has the GoogleMap
object as a parameter. Let's implement this in our activity. Take a look at the following code:
package com.raj.map; import android.app.Activity; import android.os.Bundle; import android.widget.Toast; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.MapFragment; import com.google.android.gms.maps.OnMapReadyCallback; public class MapsActivity extends Activity implements OnMapReadyCallback { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); MapFragment mapFragment = (MapFragment) getFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @Override public void onMapReady(GoogleMap map) { Toast.makeText(getApplicationContext(),"Map Ready",Toast.LENGTH_LONG).show(); map.setMyLocationEnabled(true); } }
MapsActivity.java
In the preceding code, MapsActivity
implements the OnMapReadyCallback
interface.
The getMapAsync()
method is used to enable the callback on the main thread. The callback method is defined in onMapReady()
, which has the GoogleMap
object as the parameter.
Here, we show a toast message in the callback method. For those of you who do not know what a toast is, it is a pop up used to display messages.
The setMyLocationEnabled()
method is used to enable the location
button on MapFragment
, and you can use this button to set your current location in maps using GPS.
Now, run the project. You will see the toast message and location button.

Use SupportMapFragment
in order to support lower API devices.
The GoogleMap object
The GoogleMap
object helps us to use the Google maps API effectively and to implement many features in our application.
Some of the features are as follows:
- It can be used to add markers, overlays, and so on
- It can be used to add controls, such as pan and zoom
The GoogleMap
object can be initialized as follows:
GoogleMap map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap()
Similarly, use SupportMapFragment
and SupportFragmentManager
to support lower API devices.
After initializing the GoogleMap
object, you can use methods on the GoogleMap
object. For example, consider this code:
map.setMyLocationEnabled(true)
The preceding code enables the location button on the map fragment.
In the next section, let's take a look at some of the commonly faced problems while executing or running a program.