Android find distance and duration between two points on Google Map

In this tutorial, we are going to learn how to find the distance and duration between two points on Google Map API v2. There are situations were you might want your app to measure the distance and duration between two points on a Map, this can give an insight of how long the distance is and the time it will take to accomplish the journey.

Major part of this android tutorial on finding distance and duration between two points on a Map is adopted from my tutorial on How to draw path between two points on a Map. If you have not read the tutorial, I will suggest you read it first.

 

What we are going to achieve

1. We are going to implement a Map

2. Select two points on the Map we want find their distance and duration

3. We draw a path between the two points and calculate the distance and duration between them

Before we start it is important that that we understand what we are planning to achieve in this tutorial. I have add some screen-shot from this tutorial

 

App Screenshot

Android Map find distance

 

CREATE NEW ANDROID PROJECT

Lets start to soil our hands in code. Start up your IDE. For this tutorial, I am using the following tools and environment, feel free to use what works for you.

Windows 10

Android Studio

Sony Xperia ZL

Min SDK 14

Target SDK 23

To create a new android application project, follow the steps as stipulated below.

Go to File menu

Click on New menu

Click on Android Application

Enter Project name: AndroidMapRouteDistance

Package: com.inducesmile.androidmaproutedistance

Select Map Activity

Name your activity: MapsActivity

Keep other default selections

Continue to click on next button until Finish button is active, then click on Finish Button.

Since we selected the default android Map Activity template, Android Studio will add an xml file name google_maps_api.xml. This file is stored in the values folder inside the res folder of your android project.

When you open the file, it contains instruction on how to obtain a Google Map Key. Every request your application send to Google Map Server requires a unique key that will be used to identify your application.

Also, there is a limit to the number of request you can send in a day if your are using the free service. Your google map kep also helps Google to keep track of the number of request coming from your app.

Copy for creating a Google Map Key and paste it in a web browser and hit enter. You will see a page like this.

route1

You can create a new project or use an existing project. Click the continue button to proceed.

Click the Create AOI Key button that will appear in the next page to move over to Google API Manager page.

In the Google API Manager page, click on credentials and the key link to open the page.

route2

Add a name for your key.

Select Android apps to restrict all the request from android apps

Add the your application package name

You can generate a SHA-1 certificate fingerprint. You will find the process on the page.

Click the Save button when you are done.

Finally, copy your application Google map key to the generated google_maps_api.xml as shown.

apply plugin: 'com.android.application'
<resources>
    <!--
    TODO: Before you run your application, you need a Google Maps API key.
    To get one, follow this link, follow the directions and press "Create" at the end:
    https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&r=57:A8:DD:42:FF:9E:88:E6:EC:69:71:B7:0D:2C:%3Bcom.inducesmile.androidmapdrawroute
    You can also add your credentials to an existing key, using this line:
    57:A8:DD:42:FF:9E:88:E6:EC:69:71:B7:0D:2C::46;com.inducesmile.androidmapdrawroute
    Alternatively, follow the directions here:
    https://developers.google.com/maps/documentation/android/start#get-key
    Once you have your key (it starts with "AIza"), replace the "google_maps_key"
    string in this file.
    -->
    <string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">YOUR GOOGLE MAP API KEY HERE</string>
</resources>

 

BUILD.GRADLE

In android, since we are going to make use of user location in drawing path between two points in Google Map API, we are going to use Google Play Services. Android Location Service API is part of Google Play Services.

Since the library is too big and to avoid going beyond 64000 methods which will force use to multiDexEnabled true in the defaultConfig, we will use Location and Map libraries alone.

Inaddition to these libraries, we are going to make use of Volley network library and Gson library.

Open your application build.gradle and add the code below.

apply plugin: 'com.android.application'
android {
    compileSdkVersion 24
    buildToolsVersion "24.0.1"
    defaultConfig {
        applicationId "com.inducesmile.androidmapdrawroute"
        minSdkVersion 14
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.google.android.gms:play-services-maps:9.4.0'
    compile 'com.google.android.gms:play-services-location:9.4.0'
    compile 'com.google.code.gson:gson:2.6.1'
    compile 'com.mcxiaoke.volley:library:1.0.19'
}

 

AndroidManifest.xml

We are going to update our application androidmanifest.xml. We are going to add some user permissions. Open your AndroidManifest.xml file and add the code below.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.inducesmile.androidmaproutedistance">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:name=".network.CustomApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />

        <activity
            android:name=".MapsActivity"
            android:label="@string/title_activity_maps">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

STRINGS.XML

We are going to update our project strings.xml file located in the values folder inside the res folder. Open the file and add the code below to it.

<resources>
    <string name="app_name">AndroidMapRouteDistance</string>
    <string name="title_activity_maps">Map</string>
    <string name="route_distance">Distance</string>
    <string name="route_distance_value">40.2 Km</string>
    <string name="route_duration">Duration</string>
    <string name="route_duration_value">48 mins</string>
    <string name="server_error">Server error. Something when wrong with the server</string>
</resources>

 

COLORS.XML

Open the colors.xml file in the same location as the strings.xml file and add the code below to the file.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
    <color name="colorPrimaryText">#000000</color>
    <color name="colorSecondaryText">#737373</color>
    <color name="colorIcons">#FFFFFF</color>
    <color name="colorDivider">#737373</color>
    <color name="colorMap">#FAE6D6</color>
</resources>

 

Android Google Direction API

This android tutorial on how to find distance and duration between two points on Google Map API v2 is going to make use of android Google Direction API.

Android Google Direction API is a service that calculates directions between locations using an HTTP request.

So we are going to get the user current location as the origin and we will implement onMapClickListener which will mark the user destination.

Thereafter, we will use the Android Google Direction API to calculate the direction between the two locations. The Android Polyline is used to draw an overlay line between the two directions.

Lets move on to create a layout interface file

 

activity_maps.xml

The Map Activity uses Fragment with android:name=”com.google.android.gms.maps.SupportMapFragment”.

The complete code for the layout file is as shown.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_width="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="horizontal"
        android:background="@color/colorMap"
        android:layout_weight="2">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center"
                android:orientation="vertical">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textStyle="bold"
                    android:textSize="24sp"
                    android:textColor="@color/colorPrimaryText"
                    android:text="@string/route_distance"/>

                <TextView
                    android:id="@+id/distance_value"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="16sp"
                    android:layout_marginTop="4dp"
                    android:textColor="@color/colorAccent"
                    android:text="@string/route_distance_value"/>

            </LinearLayout>

            <View
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:background="@color/colorDivider"
                android:layout_margin="4dp"/>

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center"
                android:orientation="vertical">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textStyle="bold"
                    android:textSize="24sp"
                    android:textColor="@color/colorPrimaryText"
                    android:text="@string/route_duration"/>

                <TextView
                    android:id="@+id/duration_value"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="16sp"
                    android:layout_marginTop="4dp"
                    android:textColor="@color/colorAccent"
                    android:text="@string/route_duration_value"/>

            </LinearLayout>

        </LinearLayout>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="vertical"
        android:layout_weight="8">

        <fragment
            android:id="@+id/map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context="com.inducesmile.androidmaproutedistance.MapsActivity" />

    </LinearLayout>

</LinearLayout>

 

MapsActivity Class

In the MapsActivity class, the Android Google Map is setup my Android Studio. We need to add an interface that the class will implement.

GoogleMap.OnMapClickListener – it listens to Map event click

When the Map is load, the click event listener is attached to the Map View. Users can select a location of interest on the Map by clicking on the location. Once clicked a marker will appear there to let you know the location you have selected.

The selected location is added to a List Object, once a user has selected two different location, we will draw a path to between the two location points and calculate the distance and duration between the location.

Open the MapsActivity class and add the code below to the class.

import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import com.inducesmile.androidmaproutedistance.entityObjects.DirectionObject;
import com.inducesmile.androidmaproutedistance.entityObjects.LegsObject;
import com.inducesmile.androidmaproutedistance.entityObjects.PolylineObject;
import com.inducesmile.androidmaproutedistance.entityObjects.RouteObject;
import com.inducesmile.androidmaproutedistance.entityObjects.StepsObject;
import com.inducesmile.androidmaproutedistance.network.GsonRequest;
import com.inducesmile.androidmaproutedistance.network.VolleySingleton;
import java.util.ArrayList;
import java.util.List;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleMap.OnMapClickListener {
    private static final String TAG = MapsActivity.class.getSimpleName();
    private GoogleMap mMap;
    private List<LatLng> latLngList;
    private TextView distanceValue;
    private TextView durationValue;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        distanceValue = (TextView)findViewById(R.id.distance_value);
        durationValue = (TextView)findViewById(R.id.duration_value);
        latLngList = new ArrayList<LatLng>();
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }
    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        mMap.setOnMapClickListener(this);
    }
    @Override
    public void onMapClick(LatLng latLng) {
        if(latLngList.size() > 1){
            refreshMap(mMap);
            latLngList.clear();
            distanceValue.setText("");
            durationValue.setText("");
        }
        latLngList.add(latLng);
        Log.d(TAG, "Marker number " + latLngList.size());
        createMarker(latLng, latLngList.size());
        if(latLngList.size() == 2){
            LatLng origin = latLngList.get(0);
            LatLng destination = latLngList.get(1);
            //use Google Direction API to get the route between these Locations
            String directionApiPath = Helper.getUrl(String.valueOf(origin.latitude), String.valueOf(origin.longitude),
                    String.valueOf(destination.latitude), String.valueOf(destination.longitude));
            Log.d(TAG, "Path " + directionApiPath);
            getDirectionFromDirectionApiServer(directionApiPath);
        }
    }
    private void refreshMap(GoogleMap mapInstance){
        mapInstance.clear();
    }
    private void createMarker(LatLng latLng, int position){
        MarkerOptions mOptions = new MarkerOptions().position(latLng);
        if(position == 1){
            mOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW));
        }else{
            mOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
        }
        addCameraToMap(latLng);
        mMap.addMarker(mOptions);
    }
    private void addCameraToMap(LatLng latLng){
        CameraPosition cameraPosition = new CameraPosition.Builder()
                .target(latLng)
                .zoom(8)
                .build();
        mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
    }
    private void getDirectionFromDirectionApiServer(String url){
        GsonRequest<DirectionObject> serverRequest = new GsonRequest<DirectionObject>(
                Request.Method.GET,
                url,
                DirectionObject.class,
                createRequestSuccessListener(),
                createRequestErrorListener());
        serverRequest.setRetryPolicy(new DefaultRetryPolicy(
                Helper.MY_SOCKET_TIMEOUT_MS,
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
        VolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(serverRequest);
    }
    private Response.Listener<DirectionObject> createRequestSuccessListener() {
        return new Response.Listener<DirectionObject>() {
            @Override
            public void onResponse(DirectionObject response) {
                try {
                    Log.d("JSON Response", response.toString());
                    if(response.getStatus().equals("OK")){
                        List<LatLng> mDirections = getDirectionPolylines(response.getRoutes());
                        drawRouteOnMap(mMap, mDirections);
                    }else{
                        Toast.makeText(MapsActivity.this, R.string.server_error, Toast.LENGTH_SHORT).show();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };
        };
    }
    private void setRouteDistanceAndDuration(String distance, String duration){
        distanceValue.setText(distance);
        durationValue.setText(duration);
    }
    private List<LatLng> getDirectionPolylines(List<RouteObject> routes){
        List<LatLng> directionList = new ArrayList<LatLng>();
        for(RouteObject route : routes){
            List<LegsObject> legs = route.getLegs();
            for(LegsObject leg : legs){
                String routeDistance = leg.getDistance().getText();
                String routeDuration = leg.getDuration().getText();
                setRouteDistanceAndDuration(routeDistance, routeDuration);
                List<StepsObject> steps = leg.getSteps();
                for(StepsObject step : steps){
                    PolylineObject polyline = step.getPolyline();
                    String points = polyline.getPoints();
                    List<LatLng> singlePolyline = decodePoly(points);
                    for (LatLng direction : singlePolyline){
                        directionList.add(direction);
                    }
                }
            }
        }
        return directionList;
    }
    private Response.ErrorListener createRequestErrorListener() {
        return new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                error.printStackTrace();
            }
        };
    }
    private void drawRouteOnMap(GoogleMap map, List<LatLng> positions){
        PolylineOptions options = new PolylineOptions().width(5).color(Color.RED).geodesic(true);
        options.addAll(positions);
        Polyline polyline = map.addPolyline(options);
    }
    /**
     * Method to decode polyline points
     * Courtesy : http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
     * */
    private List<LatLng> decodePoly(String encoded) {
        List<LatLng> poly = new ArrayList<>();
        int index = 0, len = encoded.length();
        int lat = 0, lng = 0;
        while (index < len) {
            int b, shift = 0, result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lat += dlat;
            shift = 0;
            result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lng += dlng;
            LatLng p = new LatLng((((double) lat / 1E5)),
                    (((double) lng / 1E5)));
            poly.add(p);
        }
        return poly;
    }
}

 

Returned JSON Response Object from Google Direction API

The returned response object is a Json object and the direction path is stored in the Polyline class. This is the class structure of the Json response object. We are going to use the Gson library to convert it to plain Java object class.

{
   "geocoded_waypoints" : [
      {
         "geocoder_status" : "OK",
         "place_id" : "ChIJZymwbofzU0YRvgugqrVwH8Q",
         "types" : [ "street_address" ]
      },
      {
         "geocoder_status" : "OK",
         "place_id" : "EiJOeWdhdGFuIDMyLCAyNDIgMzEgSMO2cmJ5LCBTdmVyaWdl",
         "types" : [ "street_address" ]
      }
   ],
   "routes" : [
      {
         "bounds" : {
            "northeast" : {
               "lat" : 55.8541564,
               "lng" : 13.661235
            },
            "southwest" : {
               "lat" : 55.85187149999999,
               "lng" : 13.660381
            }
         },
         "copyrights" : "Map data ©2016 Google",
         "legs" : [
            {
               "distance" : {
                  "text" : "0.3 km",
                  "value" : 260
               },
               "duration" : {
                  "text" : "1 min",
                  "value" : 84
               },
               "end_address" : "Nygatan 32, 242 31 Hörby, Sweden",
               "end_location" : {
                  "lat" : 55.85187149999999,
                  "lng" : 13.660381
               },
               "start_address" : "Nygatan 12B, 242 31 Hörby, Sweden",
               "start_location" : {
                  "lat" : 55.8541564,
                  "lng" : 13.661235
               },
               "steps" : [
                  {
                     "distance" : {
                        "text" : "0.3 km",
                        "value" : 260
                     },
                     "duration" : {
                        "text" : "1 min",
                        "value" : 84
                     },
                     "end_location" : {
                        "lat" : 55.85187149999999,
                        "lng" : 13.660381
                     },
                     "html_instructions" : "Head \u003cb\u003esouth\u003c/b\u003e on \u003cb\u003eNygatan\u003c/b\u003e toward \u003cb\u003eKvarngatan\u003c/b\u003e\u003cdiv style=\"font-size:0.9em\"\u003eDestination will be on the left\u003c/div\u003e",
                     "polyline" : {
                        "points" : "o_|sIwekrAVHxBj@|Bh@nBr@d@Hb@L"
                     },
                     "start_location" : {
                        "lat" : 55.8541564,
                        "lng" : 13.661235
                     },
                     "travel_mode" : "DRIVING"
                  }
               ],
               "traffic_speed_entry" : [],
               "via_waypoint" : []
            }
         ],
         "overview_polyline" : {
            "points" : "o_|sIwekrApCt@|Bh@nBr@hAV"
         },
         "summary" : "Nygatan",
         "warnings" : [],
         "waypoint_order" : []
      }
   ],
   "status" : "OK"
}

 

EntityObject Classes

We will create the following classes to mimic the structure of the Json response object. The classes are

 

DirectionObject.java

import java.util.List;
public class DirectionObject {
    private List<RouteObject> routes;
    private String status;
    public DirectionObject(List<RouteObject> routes, String status) {
        this.routes = routes;
        this.status = status;
    }
    public List<RouteObject> getRoutes() {
        return routes;
    }
    public String getStatus() {
        return status;
    }
}

 

LegsObject.java

import java.util.List;

public class LegsObject {

 private List<StepsObject> steps;

 private DistanceObject distance;

 private DurationObject duration;

 public LegsObject(DurationObject duration, DistanceObject distance, List<StepsObject> steps) {
 this.duration = duration;
 this.distance = distance;
 this.steps = steps;
 }

 public List<StepsObject> getSteps() {
 return steps;
 }

 public DistanceObject getDistance() {
 return distance;
 }

 public DurationObject getDuration() {
 return duration;
 }
}

 

PolylineObject.java

public class PolylineObject {
    private String points;
    public PolylineObject(String points) {
        this.points = points;
    }
    public String getPoints() {
        return points;
    }
}

 

RouteObject.java

import java.util.List;
public class RouteObject {
    private List<LegsObject> legs;
    public RouteObject(List<LegsObject> legs) {
        this.legs = legs;
    }
    public List<LegsObject> getLegs() {
        return legs;
    }
}

 

StepsObjects.java

public class StepsObject {
    private PolylineObject polyline;
    public StepsObject(PolylineObject polyline) {
        this.polyline = polyline;
    }
    public PolylineObject getPolyline() {
        return polyline;
    }
}

 

Using Android Volley for Network Call

We are going to extends the Application class. Create a java class and name it CustomApplication.java.

We will create an instance of our Volley object in the class. By using a custom application class, we can access the Volley object anywhere in our application.

Add the following code to the class

import android.app.Application;
import com.android.volley.RequestQueue;
public class CustomApplication extends Application{
    private RequestQueue requestQueue;
    @Override
    public void onCreate() {
        super.onCreate();
        requestQueue = VolleySingleton.getInstance(getApplicationContext()).getRequestQueue();
    }
    public RequestQueue getVolleyRequestQueue(){
        return requestQueue;
    }
}

 

GsonRequest.java

Create a java file and name it GsonRequest.java. Open the file and add the code below to it.

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
public class GsonRequest<T> extends Request<T> {
    // create variables
    private Gson mGson = new Gson();
    private Class<T> tClass;
    private Map<String, String> headers;
    private Map<String, String> params;
    private Response.Listener<T> listener;
    public GsonRequest(int method, String url, Class<T> tClass, Response.Listener<T> listener, Response.ErrorListener errorListener) {
        super(method, url, errorListener);
        this.tClass = tClass;
        this.listener = listener;
        mGson = new Gson();
    }
    public GsonRequest(int method, String url, Class<T> tClass, Map<String, String> params, Response.Listener<T> listener, Response.ErrorListener errorListener) {
        super(method, url, errorListener);
        this.tClass = tClass;
        this.params = params;
        this.listener = listener;
        this.headers = null;
        mGson = new Gson();
    }
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        return headers != null ? headers : super.getHeaders();
    }
    @Override
    protected Map<String, String> getParams() throws AuthFailureError {
        return params;
    }
    protected void deliverResponse(T response) {
        listener.onResponse(response);
    }
    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        try {
            String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            return Response.success(mGson.fromJson(json, tClass), HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JsonSyntaxException e) {
            return Response.error(new ParseError(e));
        }
    }
}

 

VolleySingleton.java

Create a new Java class and name it VolleySingleton.java. Open the file and add the code below to it.

import android.content.Context;
import android.graphics.Bitmap;
import android.util.LruCache;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
public class VolleySingleton {
    private static VolleySingleton mInstance;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;
    private static Context mCtx;
    private VolleySingleton(Context context) {
        mCtx = context;
        mRequestQueue = getRequestQueue();
        mImageLoader = new ImageLoader(mRequestQueue, new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap> cache = new LruCache<String, Bitmap>(20);
            @Override
            public Bitmap getBitmap(String url) {
                return cache.get(url);
            }
            @Override
            public void putBitmap(String url, Bitmap bitmap) {
                cache.put(url, bitmap);
            }
        });
    }
    public static synchronized VolleySingleton getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new VolleySingleton(context);
        }
        return mInstance;
    }
    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
        }
        return mRequestQueue;
    }
    public <T> void addToRequestQueue(Request<T> req) {
        getRequestQueue().add(req);
    }
    public ImageLoader getImageLoader() {
        return mImageLoader;
    }
}

 

Helper.java

We will create a new Java file and we will name it Helper.java. Open the file and add the code below.

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
public class Helper {
    private static final String DIRECTION_API = "https://maps.googleapis.com/maps/api/directions/json?origin=";
    public static final String API_KEY = "AIzaSyCuZCfoPPUV1upJT10kJbC";
    public static final int MY_SOCKET_TIMEOUT_MS = 5000;
    public static String getUrl(String originLat, String originLon, String destinationLat, String destinationLon){
        return Helper.DIRECTION_API + originLat+","+originLon+"&destination="+destinationLat+","+destinationLon+"&key="+API_KEY;
    }
    public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
    }
}

This brings us to the end of this tutorial. I hope that you have learn something. Run your app and see for yourself.

You can download the code for this tutorial below. If you are having hard time downloading the tutorial, kindly contact me.

Remember to subscribe with your email address to be among the first to receive my new android blog post once it is published.

OTHER INTERESTING POSTS:

7 Comments

    • Henry

Add a Comment