Android'de Directions API ile Rota Çizme

Günümüzde konum bilgisi kullanarak hayatımızı birçok alanda kolaylaştırması sağlayan yazılımlar bulunmaktadır. Mobil uygulamalarda GPS, araba kullanırken ya da yaya olarak yürürken, ulaşmak istediğimiz noktaya gidebilmek için yol tarifi yapması, bulunduğunuz konum çevresinde en yakın eczaneye ulaşmak gibi birçok konuda hayatımızı kolaylaştırmaktadır. Tuğba Üstündağ bu makalesinde bu püf noktasına değiniyor.

Reklam
Android'de Directions API ile Rota Çizme
24 Haziran 2020 - 19:01
Reklam

Bu makalemde, bir Android uygulamasında Google Directions API ‘yi kullanarak haritada belirlenen iki nokta arasında nasıl bir rota çizileceğini ve bu rotaya ne kadar sürede varılacağını göstereceğim.

Örnek projemizi kodlamaya başlamadan önce bazı işlemler yapmamız gerekmektedir.Bu işlemleri sırayla yapmaya başlayalım.

1- Google Play Services Yükleme

Google haritayla ilgili bir geliştirme yapacağımızdan dolayı, Google Play Services yüklememiz gerekmektedir. Bunun için Tools->Sdk manager’ı açıp Sdk Tools bölümünden Google Play Services işaretleyip, yükleme işlemini gerçekleştirin.

2- Google Maps API Key Oluşturma

3-Gerekli Kütüphanelerin Eklenmesi

Android Studio Ide ile oluşturduğum projemin app dizinin altındaki build.gradle dosyasını açıyoruz. Dependencies kod bloklarının arasına aşağıdaki kodları yerleştirerek Google Play services kütüphanesini yüklüyoruz.

1implementation 'com.google.android.gms:play-services-maps:17.0.0'

 

4-AndroidManifest Dosyasına İlgili Ayarları Ekleme

Kullanıcının konumu belirlemek için izin tanımlamamız gerekir. Aşağıdaki izin kodunu da AndroidManifest.xml dosyasında application tag’nin üst kısmına yerleştirin.

1

AndroidManifest dosyasına, daha önce üretmiş olduğumuz Google API Key’i ekleme işlemini yapacağız. Application tag arasına aşağıda görmüş olduğunuz meta-data tag kodunun içindeki value özelliğine Google API Key’i ekleyeniz.

1
2
   android:value="AIzaSyBconZdqpSflHNcs6t-btfk0Rlo1Lex7wo" />

 

5-Xml Kodları

Haritayı gösterebilmek için SupportMapFragment sınıfını fragment ile kullanıyoruz.

1
2
3
4
5
6
7
8

    xmlns:map="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

 

4-Java Kodları

İlgili rotayı çizebilmek için ilk önce Google Map Directions web servisine API Key, başlangıç ve varış noktalarının konum bilgilerini bir url ile göndermeniz gerekir. İlgili url ile web servise bağlandığınızda, rotayı ne kadar sürede bitirebileceğiniz, rotanın kaç km olduğu, yol tarifleri hakkında detaylı bilgiler json verisi halinde gelecektir. Bu kısmı ve rotanın harita çizilmesi MainActivity sınıfında yapılmıştır. Detaylı anlatım kodlarda bulunmaktadır.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
import androidx.fragment.app.FragmentActivity;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.*;
import android.preference.PreferenceManager;
import android.widget.Toast;
import com.google.android.gms.maps.*;
import com.google.android.gms.maps.model.*;
import org.json.JSONObject;
import java.io.*;
import java.net.*;
import java.util.*;
 
public class MainActivity extends FragmentActivity implements OnMapReadyCallback {
 
    private GoogleMap mMap;
    private LatLng mOrigin;
    private LatLng mDestination;
    private Polyline mPolyline;
    ArrayList mMarkerPoints;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // SupportMapFragment ile haritayı yükleyeceğimiz arayüz elemanını tanımlıyoruz
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
 
        mapFragment.getMapAsync(this);
 
        mMarkerPoints = new ArrayList<>();
    }
    //Harita üzerinde yolun başlangıç ve bitiş noktasını imleçler ile işaretleyerek seçme
    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng point) {
                // Her lokasyon yolunu çizme işleminden sonra yeni yol çizimi için harita refresh yapılıyor
                if(mMarkerPoints.size()>1){
                    mMarkerPoints.clear();
                    mMap.clear();
                }
                mMarkerPoints.add(point);
 
                //İmleçleri oluşturan sınıfı tanımladık
                MarkerOptions options = new MarkerOptions();
                //İmleci, haritada belirtilen noktalara eklenmesi için ilgili yerin değerini atadık
                options.position(point);
                //DirectionsJSONParser sınıfında, yol süresi değerini SharedPreferences ile taşıyıp
                // imleçde gösterdik
                SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
                options.title("Duration: " +preferences.getString("duration", null));
 
                /**
                 * İmleçlerin görsellerini belirleme, Başlangıç imlecini yeşil
                 * lokasyonu bitişini belirten imleç ise kırmızı olarak belirledim
                 */
                if(mMarkerPoints.size()==1){
                    options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
                }else if(mMarkerPoints.size()==2){
                    options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
                }
 
                // Haritada marker(imleç) ekleniyor
                mMap.addMarker(options);
 
                // Google Directions web servis urlsini hazırlayan ve web servisi kullanan metodu çağırdık
                if(mMarkerPoints.size() >= 2){
                    mOrigin = mMarkerPoints.get(0);
                    mDestination = mMarkerPoints.get(1);
                    drawRoute();
                }
 
            }
        });
    }
    // Google Directions API den konum datalarını kullanabilmek için web servis ile
    //bağlantı kuracağımız url hazırlayan metodu çağırdık ve web servisi çalıştırdık
    private void drawRoute(){
        String url = getDirectionsUrl(mOrigin, mDestination);
 
        DownloadTask downloadTask = new DownloadTask();
        downloadTask.execute(url);
    }
 
    //Haritada belirttiğiniz başlangeç ve bitiş imleçlerinin koordinatlarını API Key ile kullanarak
    //çizilecek düzergah ile ilgili bilgileri elde etmek adına url olusturan metod
    private String getDirectionsUrl(LatLng origin,LatLng dest){
 
        String str_origin = "origin="+origin.latitude+","+origin.longitude;
        String str_dest = "destination="+dest.latitude+","+dest.longitude;
 
        // API Key parametre olarak hazırlama
        String key = "key=" +"AIzaSyBconZdqpSflHNcs6t-btfk0Rlo1Lex7wo";
 
        String parameters = str_origin+"&"+str_dest+"&"+key;
        String output = "json";
 
        // Oluşturduğumuz parametreleri kullanarak url yi oluşturuyoruz
        String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters;
        return url;
    }
 
    private String downloadUrl(String strUrl) throws IOException {
        String data = "";
        InputStream iStream = null;
        HttpURLConnection urlConnection = null;
        try{
            // Hazırladığımız url yi kullanarak web servise Http bağlantısı ile sağlıyoruz
            URL url = new URL(strUrl);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.connect();
 
            // webservisden gelen json datayı okuyup, data değişkenine atadık
            iStream = urlConnection.getInputStream();
 
            BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
            StringBuffer sb  = new StringBuffer();
            String line = "";
            while( ( line = br.readLine())  != null){
                sb.append(line);
            }
            //json veriyi data değişkenine atadıkve metodda return yaptık
            data = sb.toString();
            br.close();
 
        }catch(Exception e){
            //Log.d("Exception on download", e.toString());
        }finally{
            iStream.close();
            urlConnection.disconnect();
        }
        return data;
    }
 
    /** Bu sınıf da, Google Directions URL kullanarak, rotanın kaç km. olduğu, ne kadar sürede gidilebildiği
     * gibi bilgileri barındıran json datayı çektik */
    private class DownloadTask extends AsyncTask {
        @Override
        protected String doInBackground(String... url) {
            String data = "";
            try{
                data = downloadUrl(url[0]);
 
            }catch(Exception e){
                //Log.d("Background Task",e.toString());
            }
            return data;
        }
 
        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            //Google Directions bilgisini, JSON formatını parse ederek almayı sağlayan sınıf
            ParserTask parserTask = new ParserTask();
            parserTask.execute(result);
        }
    }
 
    /** Bu sınıf Google Directions bilgisini, JSON formatını parse ederek almayı sağlar  */
    private class ParserTask extends AsyncTask>> >{
        @Override
        protected List>> doInBackground(String... jsonData) {
            JSONObject jObject;
            List>> routes = null;
 
            try{
                jObject = new JSONObject(jsonData[0]);
                //DirectionsJSONParser sınıfında tüm json çözümlenir.
                DirectionsJSONParser parser = new DirectionsJSONParser();
                routes = parser.parse(jObject,MainActivity.this);
            }catch(Exception e){
                e.printStackTrace();
            }
            return routes;
        }
 
        // Json çözümlendikten sonra, harita üzerinde rotayı(path) çizmeyi sağlayan metod
        @Override
        protected void onPostExecute(List>> result) {
            ArrayList points = null;
            PolylineOptions lineOptions = null;
 
            for(int i=0;i                points = new ArrayList();
                lineOptions = new PolylineOptions();
 
                List> path = result.get(i);
 
                for(int j=0;j                    HashMap point = path.get(j);
 
                    double lat = Double.parseDouble(point.get("lat"));
                    double lng = Double.parseDouble(point.get("lng"));
                    LatLng position = new LatLng(lat, lng);
                    points.add(position);
                }
 
                //PolylineOptions ile rota üzerinde noktalar ekleyerek, çizginin rengini ve genişliğini belirleme
                lineOptions.addAll(points);
                lineOptions.width(8);
                lineOptions.color(Color.RED);
            }
 
            if(lineOptions != null) {
                if(mPolyline != null){
                    mPolyline.remove();
                }
                mPolyline = mMap.addPolyline(lineOptions);
 
            }else
                Toast.makeText(getApplicationContext(),"Rota bulanamadı", Toast.LENGTH_LONG).show();
        }
    }
 
}

DirectionsJSONParser sınıfında ise web servisden gelen Json veriyi çözümleyip, içindeki bilgileri ArrayList yapısına ekleyerek MainActivity sınıfında kullanılması sağlanmıştır. Ek olarak DirectionsJSONParser sınıfında Json veriden gelen polyline değerini (rota yolunun şifrelenmiş çizgileri) çözümleyen bir metod yazılmıştır. Bu metod sayesinde  rota yolunun çizilebilmesi için gerekli enlem, boylam değerleri elde edilir. Detaylı anlatım kodlarda bulunmaktadır.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import android.content.*;
import android.preference.PreferenceManager;
import com.google.android.gms.maps.model.LatLng;
import org.json.*;
import java.util.*;
public class DirectionsJSONParser {
    /** Google Directions URL kullanarak web servisden elde edilen JSONObject çözümlenerek,
     rotayı ne kadar sürede bitirebileceğiniz, rotanın kaç km olduğu, yol tarifleri hakkında detaylı bilgiler elde edilir   */
    public List>> parse(JSONObject jObject, Context context){
 
        List>> routes = new ArrayList<>() ;
        JSONArray jRoutes = null;
        JSONArray jLegs = null;
        JSONArray jSteps = null;
 
        try {
            jRoutes = jObject.getJSONArray("routes");
 
            for(int i=0;i                jLegs = ( (JSONObject)jRoutes.get(i)).getJSONArray("legs");
 
                JSONObject c = jLegs.getJSONObject(i);
                JSONObject vo = c.getJSONObject("duration");
                //Rotaya varış süresini, SharedPreferences nesnesine atadım. Haritada gösterimi, MainActivity sınıfında.
                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
                SharedPreferences.Editor editor = prefs.edit();
                editor.putString("duration", vo.getString("text"));
                editor.commit();
 
                List path = new ArrayList>();
                for(int j=0;j                    jSteps = ( (JSONObject)jLegs.get(j)).getJSONArray("steps");
                    for(int k=0;k                     //Polyline çözümleyerek, rota noktalarının enlem, boylam bilgisi alma
                        String polyline = "";
                        polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points");
                        List list = decodePoly(polyline);
 
                        for(int l=0;l                            HashMap hm = new HashMap();
                            hm.put("lat", Double.toString(((LatLng)list.get(l)).latitude) );
                            hm.put("lng", Double.toString(((LatLng)list.get(l)).longitude) );
                            path.add(hm);
                        }
                    }
                    routes.add(path);
                }
            }
 
        } catch (JSONException e) {
            e.printStackTrace();
        }catch (Exception e){
        }
        return routes;
    }
 
    /**
     * Polyline (rota yolunun şifrelenmiş çizgileri) çözümleyerek, rota noktalarının enlem, boylam bilgisini döner
     */
    private List decodePoly(String encoded) {
 
        List 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;
    }
}

Örneklediğim projemin kodlarını indirmek isterseniz; yapmanız gereken tek şey aşağıya koyduğum KODLARI İNDİR resmine tıklamak.

Avatar

Akıllı telefonların hızla yaygınlaştığı ve mobil uygulama geliştirme pazarında ciddi bir rekabetin içinde 2008 yılından bu yana teknolojik gelişmeleri yakından takip ederek mobil platformlarda (IOS, Android) özel uygulamalar üreten, aynı zamanda Iot yazılım (App,hardware layer),Embedded linux çözümleri ve PCB(çok katlı) kart çizimi üretebilen Smality Mobile Software adlı yazılım ekibinin kurucusuyum.

Diğer bir yandan da Gömülü (Embedded) Linux, Java (SE,ME,EE), Android Uygulama Geliştirme ve C/C++ konularında kurumsal ve bireysel eğitimler vermekteyiz.
Android alanında yapmış olduğum çalışmaları, yeni başlayan geliştiricilere yardımcı olmak amacıyla makaleleştirip, kendi bloğum yayınlamaktayım.

Blogum : http://tugbaustundag.com


  • Reklam

YORUMLAR

  • 0 Yorum
Reklam