Saturday, September 15, 2012

How To Draw Shortest Path Between Two Points in Google Map



Diagram



"The following description is based on the Google older API version ."

     New Version(Google Maps Android API v2 ) 

 Step 1

    Add New Class to Your Project call ShareData .And Type Following Code.

package com.sha;

public class SharedData {
      

    // this is a singleton class that provides a global data share for all of the
    // activities and services in the MDWrapper application      
    private static SharedData instance = null;


    private SharedData() {
        //randomizeServers();
    }
  
    // data to be shared
    private String APIKEY = "";
    private double src_lat = -1;
    private double src_lng = -1;
    private double dest_lat = -1;
    private double dest_lng = -1;
  
   
    public String getAPIKEY() {
        return APIKEY;
    }

   
    public void setAPIKEY(String aPIKEY) {
        APIKEY = aPIKEY;
    }

    
    public double getSrc_lat() {
        return src_lat;
    }

  
    public void setSrc_lat(double src_lat) {
        this.src_lat = src_lat;
    }

   
    public double getSrc_lng() {
        return src_lng;
    }

   
    public void setSrc_lng(double src_lng) {
        this.src_lng = src_lng;
    }

   
    public double getDest_lat() {
        return dest_lat;
    }

    public void setDest_lat(double dest_lat) {
        this.dest_lat = dest_lat;
    }

  
    public double getDest_lng() {
        return dest_lng;
    }

   
    public void setDest_lng(double dest_lng) {
        this.dest_lng = dest_lng;
    }

    public static SharedData getInstance() {
        if (null == instance) {
            instance = new SharedData();
        }

        return instance;
    }

}

-----------------------------------------------------------------------------

Step 2

Add  another class call CustomItemizedOverlay. And type following code.

package com.sha;

import java.util.ArrayList;

import android.graphics.drawable.Drawable;

import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.OverlayItem;

public class CustomItemizedOverlay extends ItemizedOverlay<OverlayItem> {

       private final ArrayList<OverlayItem> mapOverlays = new ArrayList<OverlayItem>();


       public CustomItemizedOverlay(Drawable defaultMarker) {
             
           super(boundCenterBottom(defaultMarker));
       }

       @Override
       protected OverlayItem createItem(int i) {
           return mapOverlays.get(i);
       }

       @Override
       public int size() {
           return mapOverlays.size();
       }

       public void addOverlay(OverlayItem overlay) {
           mapOverlays.add(overlay);
           this.populate();
       }

       }

 --------------------------------------------------------------------------------------------------------

Step3

Add  another class call MyOverlay. And type following code.

package com.sha;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

public class MyOverLay extends Overlay
{
    private GeoPoint gp1;
    private GeoPoint gp2;
    private int mode=0;
    private int defaultColor;
    Context mContext;

    public MyOverLay(Context context,GeoPoint gp1,GeoPoint gp2,int mode) // GeoPoint is a int. (6E)
    {
        this.gp1 = gp1;
        this.gp2 = gp2;
        this.mode = mode;
        this.mContext = context;
        defaultColor = 999; // no defaultColor

    }

    public MyOverLay(GeoPoint gp1,GeoPoint gp2,int mode, int defaultColor)
    {
        this.gp1 = gp1;
        this.gp2 = gp2;
        this.mode = mode;
        this.defaultColor = defaultColor;
    }
    public int getMode()
    {
        return mode;
    }

    @Override
    public boolean draw
    (Canvas canvas, MapView mapView, boolean shadow, long when)
    {
        Projection projection = mapView.getProjection();
        if (shadow == false)
        {
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            Point point = new Point();
            projection.toPixels(gp1, point);
            // mode=1&#65306;start
            if(mode==1)
            {
                if(defaultColor==999)
                    paint.setColor(Color.BLUE);
                else
                    paint.setColor(defaultColor);              
                // start point
            }
            // mode=2&#65306;path
            else if(mode==2)
            {
                if(defaultColor==999)
                    paint.setColor(Color.RED);
                else
                    paint.setColor(defaultColor);
                Point point2 = new Point();
                projection.toPixels(gp2, point2);
                paint.setStrokeWidth(5);
                paint.setAlpha(120);
                canvas.drawLine(point.x, point.y, point2.x,point2.y, paint);
              
            }
            /* mode=3&#65306;end */
            else if(mode==3)
            {
                /* the last path */

                if(defaultColor==999)
                    paint.setColor(Color.GREEN);
                else
                    paint.setColor(defaultColor);
                Point point2 = new Point();
                projection.toPixels(gp2, point2);
                paint.setStrokeWidth(5);
                paint.setAlpha(120);
                canvas.drawLine(point.x, point.y, point2.x,point2.y, paint);
                /* end point */
              
            }
        }
        return super.draw(canvas, mapView, shadow, when);
    }

}


Step 4

Add  another class call RoutePath. And type following code.

package com.sha;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
//import com.sha.SharedDataActivity.connectAsyncTask;

public class RoutePath extends MapActivity {
    /** Called when the activity is first created. */
    MapView mapView;
    private RoutePath _activity;
    GeoPoint srcGeoPoint,destGeoPoint;
    private static List<Overlay> mOverlays;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedData data = SharedData.getInstance();
        mapView = new MapView(this,data.getAPIKEY());
        mapView.setClickable(true);      
        setContentView(mapView);
        _activity = this;
        double src_lat = data.getSrc_lat();
        double src_long = data.getSrc_lng();
        double dest_lat = data.getDest_lat();
        double dest_long = data.getDest_lng();

        if(src_lat == -1 || src_long == -1 || dest_lat == -1 || dest_long == -1){
            showAlert("Please enter source and destination points");
        }else{

            srcGeoPoint = new GeoPoint((int) (src_lat * 1E6),(int) (src_long * 1E6));
            destGeoPoint = new GeoPoint((int) (dest_lat * 1E6),(int) (dest_long * 1E6));

            List<Overlay> mapOverlays = mapView.getOverlays();
            Drawable srcdrawable = this.getResources().getDrawable(R.drawable.ic_launcher);
            CustomItemizedOverlay srcitemizedOverlay = new CustomItemizedOverlay(srcdrawable);
            //CustomItemizedOverlay srcitemizedOverlay = new CustomItemizedOverlay(getDrawable("com/agarwal/route/pin_green.png"));
            OverlayItem srcoverlayitem = new OverlayItem(srcGeoPoint, "Hello!", "This is your Location.");

            Drawable destdrawable = this.getResources().getDrawable(R.drawable.ic_launcher);
            CustomItemizedOverlay  destitemizedOverlay = new CustomItemizedOverlay( destdrawable );
           // CustomItemizedOverlay destitemizedOverlay = new CustomItemizedOverlay(getDrawable("com/agarwal/route/pin_red.png"));
            OverlayItem destoverlayitem = new OverlayItem(destGeoPoint, "Hello!", "This is dest Location.");

            srcitemizedOverlay.addOverlay(srcoverlayitem);
            destitemizedOverlay.addOverlay(destoverlayitem);

            mapOverlays.add(srcitemizedOverlay);
            mapOverlays.add(destitemizedOverlay);

            connectAsyncTask _connectAsyncTask = new connectAsyncTask();
            _connectAsyncTask.execute();      
            mapView.setBuiltInZoomControls(true);
            mapView.displayZoomControls(true);
            mOverlays = mapView.getOverlays();
            mapView.getController().animateTo(srcGeoPoint);
            mapView.getController().setZoom(12);
        }
    }
    @Override
    protected boolean isRouteDisplayed() {
        // TODO Auto-generated method stub
        return false;
    }

    private class connectAsyncTask extends AsyncTask<Void, Void, Void>{
        private ProgressDialog progressDialog;
        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();
            progressDialog = new ProgressDialog(_activity);
            progressDialog.setMessage("Fetching route, Please wait...");
            progressDialog.setIndeterminate(true);
            progressDialog.show();
        }
        @Override
        protected Void doInBackground(Void... params) {
            // TODO Auto-generated method stub
            fetchData();
            return null;
        }
        @Override
        protected void onPostExecute(Void result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);          
            if(doc!=null){
                Overlay ol = new MyOverLay(_activity,srcGeoPoint,srcGeoPoint,1);
                mOverlays.add(ol);
                NodeList _nodelist = doc.getElementsByTagName("status");
                Node node1 = _nodelist.item(0);
                String _status1  = node1.getChildNodes().item(0).getNodeValue();
                if(_status1.equalsIgnoreCase("OK")){
                    NodeList _nodelist_path = doc.getElementsByTagName("overview_polyline");
                    Node node_path = _nodelist_path.item(0);
                    Element _status_path = (Element)node_path;
                    NodeList _nodelist_destination_path = _status_path.getElementsByTagName("points");
                    Node _nodelist_dest = _nodelist_destination_path.item(0);
                    String _path  = _nodelist_dest.getChildNodes().item(0).getNodeValue();
                    List<GeoPoint> _geopoints = decodePoly(_path);
                    GeoPoint gp1;
                    GeoPoint gp2;
                    gp2 = _geopoints.get(0);
                    Log.d("_geopoints","::"+_geopoints.size());
                    for(int i=1;i<_geopoints.size();i++) // the last one would be crash
                    {

                        gp1 = gp2;
                        gp2 = _geopoints.get(i);
                        Overlay ol1 = new MyOverLay(gp1,gp2,2,Color.BLUE);
                        mOverlays.add(ol1);
                    }
                    Overlay ol2 = new MyOverLay(_activity,destGeoPoint,destGeoPoint,3);
                    mOverlays.add(ol2);

                    progressDialog.dismiss();
                }else{
                    showAlert("Unable to find the route");
                }

                Overlay ol2 = new MyOverLay(_activity,destGeoPoint,destGeoPoint,3);
                mOverlays.add(ol2);
                progressDialog.dismiss();
                mapView.scrollBy(-1,-1);
                mapView.scrollBy(1,1);
            }else{
                showAlert("Unable to find the route");
            }

        }

    }
    Document doc = null;
    private void fetchData()
    {
        StringBuilder urlString = new StringBuilder();
        urlString.append("http://maps.google.com/maps/api/directions/xml?origin=");
        urlString.append( Double.toString((double)srcGeoPoint.getLatitudeE6()/1.0E6 ));
        urlString.append(",");
        urlString.append( Double.toString((double)srcGeoPoint.getLongitudeE6()/1.0E6 ));
        urlString.append("&destination=");//to
        urlString.append( Double.toString((double)destGeoPoint.getLatitudeE6()/1.0E6 ));
        urlString.append(",");
        urlString.append( Double.toString((double)destGeoPoint.getLongitudeE6()/1.0E6 ));
        urlString.append("&sensor=true&mode=driving");   
        Log.d("url","::"+urlString.toString());
        HttpURLConnection urlConnection= null;
        URL url = null;
        try
        {
            url = new URL(urlString.toString());
            urlConnection=(HttpURLConnection)url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.connect();
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            doc = (Document) db.parse(urlConnection.getInputStream());//Util.XMLfromString(response);
        }catch (MalformedURLException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }catch (ParserConfigurationException e){
            e.printStackTrace();
        }
        catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    private List<GeoPoint> decodePoly(String encoded) {

        List<GeoPoint> poly = new ArrayList<GeoPoint>();
        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;

            GeoPoint p = new GeoPoint((int) (((double) lat / 1E5) * 1E6),
                    (int) (((double) lng / 1E5) * 1E6));
            poly.add(p);
        }

        return poly;
    }
    private void showAlert(String message){
        AlertDialog.Builder alert = new AlertDialog.Builder(_activity);
        alert.setTitle("Error");
        alert.setCancelable(false);
        alert.setMessage(message);
        alert.setPositiveButton("Ok",new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub

            }
        });
        alert.show();
    }
    private Drawable getDrawable(String fileName){
        return Drawable.createFromStream(_activity.getClass().getClassLoader().getResourceAsStream(fileName), "pin");
    }
}

Step5

Finally  type following code for your Main Activity class. In Here My One is SharedDataActivity class.

 To generate api key of you, please  follow my blog :-

 http://adrianandroid.blogspot.com/2012/07/android-google-map-tutorial-01loading.html

package com.sha;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;




public class SharedDataActivity extends Activity {
    /** Called when the activity is first created. */
 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.adrian);
       
        SharedData data = SharedData.getInstance();
// to generate api key
        data.setAPIKEY("0yKpGoapYdqNTNFYO-qbnqjzPuGlzK5hyI52Ghw");
        data.setSrc_lat(6.914892);// malbe SLIIT
        data.setSrc_lng(79.973289);
        data.setDest_lat(6.827409);// Bandarawela (Home Town)
        data.setDest_lng(80.985346);
      
        startActivity(new Intent(SharedDataActivity.this,RoutePath.class));
    }
 
}

---------------------------------------------------------------------------------------------------    

 this is  adrian.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
   

</LinearLayout>

 --------------------------------------------------------------------------------------------------

Android Manifest 

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

    <uses-sdk android:minSdkVersion="7" />

          <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
   
   
   
   
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
       
        <uses-library android:name="com.google.android.maps" />
       
       
       
        <activity
            android:name=".SharedDataActivity"
            android:label="@string/app_name" >
           
           
           
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

----------------------------------------------------------------------------------

 Run your App

 Good Luck!

  Tutorial List