Last Updated on 10 years by Hafizh Herdi
Selamat sore semuanya, pada kesempatan kali ini saya akan membahas tentang bagaimana cara menampilkan rute atau direction antara dua buah koordinat pada Android Maps API V2. Sebenarnya banyak tutorial lainnya yang membahas tentang ini, namun kebanyakan tutorial tersebut menampilkan rute dengan cara menampilkan rute-nya pada aplikasi native Google Maps. Berbeda dengan tutorial ini, tutorial ini akan benar-benar menampilkan rute pada aplikasi Android Maps yang kalian buat. 🙂 Bagaimana caranya? Yuk kita lihat.
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. 😀 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<LatLng> getDirection (Document doc) { NodeList nl1, nl2, nl3; ArrayList<LatLng> listGeopoints = new ArrayList<LatLng>(); 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<LatLng> 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<LatLng> decodePoly(String encoded) { ArrayList<LatLng> poly = new ArrayList<LatLng>(); 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<LatLng> 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 :
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.
masih bingung nih , ada semple gag mas ?
makasih sebelum’nya
mas yang diganti itu MainActivity.java menjadi MapDirection.java ya mas?
tutor yang ini membingunkan mas, beda dengan sebelumnya mas, hehehe
maaf kepo, ane newbie, maklum masih smk udah disuruh buat tugas ini, hehehehhe
mohon bantuannya mas, 🙂
thanks 🙂
mas, script yang ini ditaruh dimana ya mas? kok cara yang ini membingungkan mas, heheheh
Yup, memang ini hanya gambaran besarnya bro.
Jadi pertama, gunakan AsyncTask untuk download directionPoint , setelah itu masukkan point2 pada direction itu ke polyLineOptions, setelah itu baru ditampilkan di peta. 🙂
mas..
kalo direction ya itu titik pertama dari posisi kita gmana yah mas,,,
minta bimbinganya,,,,
mas kalau ingin mendapatkan rute tercepat lebih dari dua titik katakanlah 5 titik, dengan syarat tidak boleh melewati titik yang sama bagaimana?
Selamat Malam mas,
mau tanya, tutorial di atas itu memasukkan koordinatnya secara manual ya mas?
Posisi pengguna pun terpaku pada 1 titik mas? atau otomatis berubah dimana pun kita berada?
Maaf mas kalo bikin bingung :v
Kalo boleh tau sumber code map direction nya dari mana mas ? mau tau lebih jauh apakah code tsb support untuk selain google map API (contohnya Openstreetmap) ?
saat ini belum support, sumber code maps directionnya langsung dari Google Map API
maaf,mas.
kalo mau mencari jalur terpendek menggunakan algoritma greedy di android apakah bisaa?
thx
mas.. tutorial di atas kalo koordinat nya banyak gma penerapan nya ?? ketika di pencet marker langsung menuju lokasi nya?
makasihh
Akhrnya berhasil mas..
Terima kasih buat ilmunya 🙂
Mantaap… demen bgt nih kalo ada yg berhasil kayak gini hahha
bisa ajarin saya ga mas marshel
itu asynctasknya dipanggil dimana? saya masih belum paham. mohon bantuannya. Terima kasih
Asynctask nya dipanggil pada kelas terpisah, silahkan di explore lebih lanjut bagaimana cara penggunaan Asynctask 🙂
Saya kecewa dengan tutorialnya, terlalu bertele-tele dari satu halaman harus buka halaman lain. Sebelum membuat project E kami harus bukan Project D dan C kemudian sebelum ke Project C lebih baik ke A lalu ke B. Kenapa tidak dibuat sekalian saja tutornya dalam 1 halaman ?
Sudah baca sampai habis malah di bilang belum tentu benar tutorialnya. Niat bagi gak sih sebenarnya ? kalo gak hapus aja artikelnya. Karena buat orang kecewa, di google pencarian no 1 tapi tutornya buat kecewa !!!
Thx atas masukannya om… Ya namanya tutorial dimana-mana pasti ada step by step dan bagian2 yang harus dilakukan pertahap, coba lihat tutorial by Google https://developers.google.com/maps/documentation/android-api/start itu ada beberapa halaman yang harus dibaca dan dipelajari sebelum berhasil membuat tutorial tersebut. Di sini kami ingin pembaca benar2 paham dan belajar, tidak hanya sekadar copas sehingga memang banyak yang harus dibaca dan dipelajari. Seperti tutorial artikel di atas itu emang sengaja saya tulis garis besar logic nya saja supaya pembaca mau belajar mengembangkan kreativitasnya tidak hanya copas.
Kalo boleh tahu tutorial mana yang saya pernah bilang belum tentu benar tutorialnya? Kalo memang ada nanti akan direvisi.
Dan kalo kecewa silahkan masih banyak situs no2,3,4 dst yang bisa ente kunjungi di mbah Google 🙂
makasih buat tutorialnya..sangat membantu…
tapi boleh tanya gak..gimana caranya ngambil koordinat dr tempatkita berada saat menggunakan androidnya..?
Mas, saat saya coba tutorialnya bagian ini kok merah ya?
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;
apakah ada library yang harus ditambahkan ?
itu harus ditambahkan use apache http legacy, karena semua package di atas sudah deprecated
assalamualaikum wr.wb
hallo mas hafizh saya sudah berhasil membuat petanya, tutorialnya sangat mudah dicerna, oiya mas untuk get directionnya itu bisa kita custom menggunakan algoritma pencarian jarak terdekat seperti floyd warshall atau algoritma pencarian jarak terdekat yang lain tidak ya mas,, menurut jurnal yang saya baca, algoritma default yang dipakai google maps itu menggunakan algoritma djikstra mas, bagaimana ya mas? mohon pencerahannya,, terimakasih sebelumnya,,,,
Wassalamualaikum wr.wb
mas.. itu kan kalo dari tandean startnya.. terus kalo mau dari lokasi sayang sekarang misalnya gimana mas? tandean nya di ganti jadi apa?
*saya maksudnya hehe
Wah ini ngambil dari mas agus ya