Menampilkan Rute Tercepat (Driving Direction) Antara Dua Koordinat pada Android Maps V2

Android Maps V2 Draw Direction

Pertama-tama, pastikan kalian telah bisa menampilkan peta pada Android, ikuti tutorial Android Maps V2 di sini. Setelah itu sediakan dua buah koordinat latitude dan longitude, jika saya koordinat pertama adalah lokasi saya berada (misalnya -6.248000,106.8322), dan koordinat kedua adalah lokasi Monas (-6.1755, 106.8273).
Setelah itu, saya menemukan sebuah kelas semacam library yang siap pakai, untuk menampilkan rute tercepat di antara dua buah titik / koordinat pada Android Maps V2. Karena open source, maka saya ganti nama kelasnya menjadi MapDirection. :D Inilah isi dari class MapDirection.java.
package id.web.twoh.www.mapsv2;
 
import java.io.InputStream;
import java.util.ArrayList;
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
 
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
 
import com.google.android.gms.maps.model.LatLng;
import android.annotation.SuppressLint;
import android.util.Log;
 
@SuppressLint("NewApi")
public class MapDirection {
    public final static String MODE_DRIVING = "driving";
    public final static String MODE_WALKING = "walking";
 
    public MapDirection() { }
 
    public Document getDocument(LatLng start, LatLng end, String mode) {
        String url = "http://maps.googleapis.com/maps/api/directions/xml?"
                + "origin=" + start.latitude + "," + start.longitude 
                + "&destination=" + end.latitude + "," + end.longitude
                + "&sensor=false&units=metric&mode=driving";
 
        try {
            HttpClient httpClient = new DefaultHttpClient();
            HttpContext localContext = new BasicHttpContext();
            HttpPost httpPost = new HttpPost(url);
            HttpResponse response = httpClient.execute(httpPost, localContext);
            InputStream in = response.getEntity().getContent();
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = builder.parse(in);
            return doc;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
 
    public String getDurationText (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("duration");
        Node node1 = nl1.item(nl1.getLength() - 1);
        NodeList nl2 = node1.getChildNodes();
        Node node2 = nl2.item(getNodeIndex(nl2, "text"));
        Log.i("DurationText", node2.getTextContent());
        return node2.getTextContent();
    }
 
    public int getDurationValue (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("duration");
        Node node1 = nl1.item(nl1.getLength() - 1);
        NodeList nl2 = node1.getChildNodes();
        Node node2 = nl2.item(getNodeIndex(nl2, "value"));
        Log.i("DurationValue", node2.getTextContent());
        return Integer.parseInt(node2.getTextContent());
    }
 
    public String getDistanceText (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("distance");
        Node node1 = nl1.item(nl1.getLength() - 1);
        NodeList nl2 = node1.getChildNodes();
        Node node2 = nl2.item(getNodeIndex(nl2, "text"));
        Log.i("DistanceText", node2.getTextContent());
        return node2.getTextContent();
    }
 
    public int getDistanceValue (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("distance");
        Node node1 = nl1.item(nl1.getLength() - 1);
        NodeList nl2 = node1.getChildNodes();
        Node node2 = nl2.item(getNodeIndex(nl2, "value"));
        Log.i("DistanceValue", node2.getTextContent());
        return Integer.parseInt(node2.getTextContent());
    }
 
    public String getStartAddress (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("start_address");
        Node node1 = nl1.item(0);
        Log.i("StartAddress", node1.getTextContent());
        return node1.getTextContent();
    }
 
    public String getEndAddress (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("end_address");
        Node node1 = nl1.item(0);
        Log.i("StartAddress", node1.getTextContent());
        return node1.getTextContent();
    }
 
    public String getCopyRights (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("copyrights");
        Node node1 = nl1.item(0);
        Log.i("CopyRights", node1.getTextContent());
        return node1.getTextContent();
    }
 
    public ArrayList getDirection (Document doc) {
        NodeList nl1, nl2, nl3;
        ArrayList listGeopoints = new ArrayList();
        nl1 = doc.getElementsByTagName("step");
        if (nl1.getLength() > 0) {
            for (int i = 0; i < nl1.getLength(); i++) {
                Node node1 = nl1.item(i);
                nl2 = node1.getChildNodes();
 
                Node locationNode = nl2.item(getNodeIndex(nl2, "start_location"));
                nl3 = locationNode.getChildNodes();
                Node latNode = nl3.item(getNodeIndex(nl3, "lat"));
                double lat = Double.parseDouble(latNode.getTextContent());
                Node lngNode = nl3.item(getNodeIndex(nl3, "lng"));
                double lng = Double.parseDouble(lngNode.getTextContent());
                listGeopoints.add(new LatLng(lat, lng));
 
                locationNode = nl2.item(getNodeIndex(nl2, "polyline"));
                nl3 = locationNode.getChildNodes();
                latNode = nl3.item(getNodeIndex(nl3, "points"));
                ArrayList arr = decodePoly(latNode.getTextContent());
                for(int j = 0 ; j < arr.size() ; j++) {
                    listGeopoints.add(new LatLng(arr.get(j).latitude, arr.get(j).longitude));
                }
 
                locationNode = nl2.item(getNodeIndex(nl2, "end_location"));
                nl3 = locationNode.getChildNodes();
                latNode = nl3.item(getNodeIndex(nl3, "lat"));
                lat = Double.parseDouble(latNode.getTextContent());
                lngNode = nl3.item(getNodeIndex(nl3, "lng"));
                lng = Double.parseDouble(lngNode.getTextContent());
                listGeopoints.add(new LatLng(lat, lng));
            }
        }
 
        return listGeopoints;
    }
 
    private int getNodeIndex(NodeList nl, String nodename) {
        for(int i = 0 ; i < nl.getLength() ; i++) {
            if(nl.item(i).getNodeName().equals(nodename))
                return i;
        }
        return -1;
    }
 
    private ArrayList decodePoly(String encoded) {
        ArrayList 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 position = new LatLng((double) lat / 1E5, (double) lng / 1E5);
            poly.add(position);
        }
        return poly;
    }
}
Pada dasarnya, kelas tersebut akan menerima inputan berupa dua buah koordinat, titik awal dan titik akhir. Untuk kemudian di decode menggunakan Google Maps APIs, yang menghasilkan sebuah file XML. Nah, selanjutnya XML tersebut akan diubah menjadi sebuah ArrayList berisi LatLng (titik koordinat latitude dan longitude). Nantinya array dari latitude dan longitude itulah yang akan digunakan untuk menampilkan rute pada Android Maps V2.
Untuk menggunakan kelas tersebut, cukup copy source code di atas ke file MapDirection.java dan masukkan ke dalam project kalian. Kemudian berikut ini adalah cara memanggil kelas MapDirection tersebut :
//...
// sediakan dua buah koordinat
 
LatLng TENDEAN = new LatLng(-6.248000,106.8322);
LatLng MONAS = new LatLng(-6.1755, 106.8273); 
 
// inisialisasi kelas
 
MapDirection MapDirection md = new MapDirection();         
LatLng source = TENDEAN;           
 
    //download document XML
Document doc = md.getDocument(source, MONAS, MapDirection.MODE_DRIVING);
    // menggunakan mode driving 
 
// method untuk mendapatkan point direction / rute         
ArrayList directionPoint = md.getDirection(doc); 
 
// konfigurasi rute, warna garis, ketebalan, dan sebagainya            
PolylineOptions rectLine = new PolylineOptions().width(5).color(Color.RED); 
 
// looping pada array koordinat direction point, dan menambahkannya ke PolyLineOptions         
 
for (int i = 0; i < directionPoint.size(); i++)
{              
    rectLine.add(directionPoint.get(i));           
} 
 
// menampilkan rute di peta yang kita buat         
googleMap.addPolyline(rectLine); 
 
//.... 
Begitulah caranya, pada kode di atas pertama-tama kita akan meminta Document XML-nya terlebih dahulu dengan memanggil fungsi getDocument(source,destination). Setelah kita mendapatkan document xml tersebut, baru kita parsing menjadi array koordinat lat long menggunakan fungsi getDirection(doc).
Setelah kita mendapatkan array koordinat, (ingat, garis adalah kupulan dari titik, jadi untuk bisa menampilkan sebuah rute yang berupa garis, kita perlu banyak titik-titik), kita akan menambahkan koordinat itu satu persatu ke dalam PolyLineOptions. PolyLineOptions adalah suatu kelas yang selain berfungsi untuk menampung array of koordinat tersebut, juga bisa berfungsi untuk mengatur warna garis rute, ketebalan, dan sebagainya. Selanjutnya, kita akan menampilkan rute tersebut pada Android Maps dalam bentuk PolyLine.
Dan, inilah hasilnya :
route_androidmapsv2 
Menampilkan rute pada Android Maps V2
route_androidmapsv2_bv 
Berhasil kan. :) Sekian, semoga membantu.
NOTE : kode untuk pemanggila kelas MapDirection di atas hanyalah sebagai hint/petunjuk. Jangan kalian copy mentah-mentah. Saya sarankan menerapkannya pada sebuah AsyncTask Class yang akan mendownload file XML tersebut pada background. Jika kalian langsung menerapkan tanpa AsyncTask atau di main class, maka akan terjadi NetworkOnMainThreadException, yang akan menyebabkan aplikasi force close.

by : ARP

Sumber : http://www.twoh.co/2013/09/menampilkan-rute-tercepat-driving-direction-di-antara-dua-koordinat-pada-android-maps-v2/