Learning Android Google Maps
上QQ阅读APP看书,第一时间看更新

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:

Creating our first map application

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

Creating our first map application

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:

Optional (for old APIs)

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>

activity_maps.xml – code 3

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.

Using the callback method

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.