Как использовать Driving Directions и MapView на платформе Android

Опубликовано: 11/08/2010, автор: Администратор, категория: Разное

В этой статье приведу простой пример использования MapView и Driving Directions в своих приложениях. Достигнуть поставленной цели можно двумя способами:
Использовать приложение Maps.

Intent myIntent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(«http://maps.google.com/maps?
f=d&hl=ru&saddr=55.854722232222,37.476111121111&daddr=55.966666667667,37.400000001&ie=UTF8&om=0&output=kml»));
startActivity(myIntent);

Результат:

Этот способ не требует никаких усилий от программиста, но для его реализации потребуется вызов сторонней программы. Если это недопустимо, то можно прибегнуть к более трудозатратному делу, а именно написать весь код по получению Driving Directions самому. Итак, приступим.

Создадем приложение с вот такой компановкой:

<?xml version=»1.0″ encoding=»utf-8″?>
<LinearLayout xmlns:android=»http://schemas.android.com/apk/res/android»
android:orientation=»vertical»
android:layout_width=»fill_parent»
android:layout_height=»fill_parent»
android:background=»#FFFFFF»>
<com.google.android.maps.MapView
android:id=»@+id/mapview»
android:layout_width=»fill_parent»
android:layout_height=»fill_parent»
android:layout_weight=»1″
android:apiKey=»Ваш apiKey»
android:clickable=»true»/>
<TextView
android:id=»@+id/TextView01″
android:layout_height=»wrap_content»
android:layout_width=»fill_parent»
android:text=»Driving directions»
android:textColor=»#000000″>
</TextView>
<ScrollView
android:id=»@+id/ScrollView01″
android:layout_width=»fill_parent»
android:layout_height=»fill_parent»
android:layout_weight=»2″>
<TextView
android:id=»@+id/route»
android:layout_width=»fill_parent»
android:layout_height=»fill_parent»
android:textColor=»#000000″>
</TextView>
</ScrollView>
</LinearLayout>

При создании проекта указать BuildTarget — GoogleApis
В манифесте в <application> добавить:

<uses-library android:name=»com.google.android.maps» />

А также разрешить доступ в интернет:

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

Чтобы получить информацию о пути между двумя точками нужно послать HTTP запрос по следующему адресу:
«http://maps.google.com/maps?f=d&hl=ru&saddr=55.854722232222,37.476111121111&daddr=55.966666667667,37.400000001&ie=UTF8&om=0&output=kml»
естественно вставив нужные координаты начальной и конечной точки.
В ответ мы получим файл maps.xml, в котором содержится вся необходимая нам информация и который мы будем парсить при помощи DOM.

String urlString = «http://maps.google.com/maps?f=d&hl=ru&saddr=»
+ srcLat + «,» + srcLon + «&daddr=» + dstLat + «,» + dstLon
+ «&ie=UTF8&0&om=0&output=kml»;

Document doc = null;
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 = db.parse(urlConnection.getInputStream());

} catch (Exception e) {
Log.e(«parse error», «parsing is not succesful»);
}

В полученном xml файле для каждого отрезка пути нам нужно найти следующие теги:


<Placemark>
<name>Направляйтесь на юго-запад по ул. Фестивальная в направлении ш. Ленинградское</name>


<Point>
<coordinates>37.475950,55.854890,0</coordinates>
</Point>

Они содержат описание отрезка пути и координаты его начала.
Потом получим координаты всех точек пути:

<GeometryCollection>
<LineString>
<coordinates>37.475950,55.854890,0.000000 37.474170,55.854420,0.000000 37.471360,55.853790,0.000000

</coordinates>
</LineString>
</GeometryCollection>

Полученную информацию каждый может использовать по своему вкусу. Далее полный листинг программы.

//**********************************
//Листинг DrivingDirectionsDemo.java
//**********************************

package com.evtgroup.dd;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import android.app.ProgressDialog;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;

public class DrivingDirectionsDemo extends MapActivity {

    private MapView mapView;
    private MapController mc;
    private String[] routeContent;
    private ProgressDialog progressDialog;
    private ArrayList<String> route = new ArrayList<String>();
    private String[] distances;

    private static final double SRC_LAT = 55.854722232222;
    private static final double SRC_LON = 37.476111121111;
    private static final double DST_LAT = 55.966666667667;
    private static final double DST_LON = 37.400000001;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mapView = (MapView)findViewById(R.id.mapview);
        mapView.setBuiltInZoomControls(true);
        mapView.setEnabled(true);
        mapView.setSatellite(false);
        mapView.displayZoomControls(true);

        mc = mapView.getController();
        mc.setZoom(12);
        GeoPoint srcPoint = new GeoPoint((int)(SRC_LAT*1E6), (int)(SRC_LON*1E6));
        mc.animateTo(srcPoint);

        ConnectionThread thread = new ConnectionThread(new ConnectionHandler());
        thread.setState(SRC_LAT + "", SRC_LON + "", DST_LAT + "", DST_LON + "");
        progressDialog = ProgressDialog.show(this, "", "Загрузка...", true);
        thread.start();
    }

    // Поток для запроса данных
    private class ConnectionThread extends Thread{

        private Handler handler;
        private String srcLat, srcLon, dstLat, dstLon;

        // Конструктор потока
        ConnectionThread(Handler h){
            handler = h;
        };

        public void run(){
            boolean res = getDirectionData(srcLat, srcLon, dstLat, dstLon);
            Bundle b = new Bundle();
            b.putBoolean("res", res);
            Message msg = handler.obtainMessage();
            msg.setData(b);
            handler.sendMessage(msg);
        }

        public void setState(String slat, String slon, String dlat, String dlon){
            srcLat = slat;
            srcLon = slon;
            dstLat = dlat;
            dstLon = dlon;
        }
    }

    private class ConnectionHandler extends Handler{

        public void handleMessage(Message msg){
            progressDialog.dismiss();

            if (!msg.getData().getBoolean("res")){            //Данные не получены
                ((TextView)findViewById(R.id.route)).setText("Данные не получены!");
            }else{

                String[] lonLat = routeContent[0].split(",");
                //Добавляем точки пути
                GeoPoint gp1 = new GeoPoint((int)(Double.parseDouble(lonLat[1])*1E6),
                        (int)(Double.parseDouble(lonLat[0])*1E6));
                GeoPoint gp2;
                for (int i = 1; i < routeContent.length; i++) {
                    lonLat = routeContent[i].split(",");
                    gp2 = new GeoPoint((int)(Double.parseDouble(lonLat[1])*1E6),
                            (int)(Double.parseDouble(lonLat[0])*1E6));
                    mapView.getOverlays().add(new DirectionPathOverlay(gp1, gp2));
                    gp1 = gp2;
                }

                // Показываем driving directions
                String str = "";
                for (int i = 0; i < route.size()-1; i++){
                    str = str + (i+1) + ". " + route.get(i) + " - " + distances[i] + "\n";
                }
                str = str + (route.size()-1) + ". " + route.get(route.size()-1);
                ((TextView)findViewById(R.id.route)).setText(str);
            }
        }

    }

    private boolean getDirectionData(String srcLat, String srcLon, String dstLat, String dstLon) {

        String urlString = "http://maps.google.com/maps?f=d&hl=ru&saddr="
                + srcLat + "," + srcLon + "&daddr=" + dstLat + "," + dstLon
                + "&ie=UTF8&0&om=0&output=kml";

        Document doc = null;
        HttpURLConnection urlConnection = null;
        URL url = null;
        String pathContent = "";
        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 = db.parse(urlConnection.getInputStream());

        } catch (Exception e) {
            Log.e("parse error", "parsing is not succesful");
            return false;
        }

        //Получаем массив строк с координатами пути
        NodeList nl = doc.getElementsByTagName("LineString");
        Node n = nl.item(0);
        pathContent = n.getFirstChild().getFirstChild().getNodeValue();
        routeContent = pathContent.split(" ");

        //Получаем направления пути
        nl = doc.getElementsByTagName("name");
        for (int s = 1; s < nl.getLength()-1; s++){
            Node rootNode = nl.item(s);
            String r = rootNode.getFirstChild().getNodeValue();
            route.add(r);
        }

        //Получаем координаты опорных точек направлений пути
        ArrayList<String[]> coords = new ArrayList<String[]>();
        nl = doc.getElementsByTagName("coordinates");
        for (int s = 0; s < nl.getLength()-1; s++){
            Node rootNode = nl.item(s);
            String r = rootNode.getFirstChild().getNodeValue();
            coords.add(r.split(","));
        }

        //Получаем расстояния между опорными точками в км
        distances = new String[coords.size()-1];
        for (int i = 0; i < coords.size()-1; i++){
            Location locationA = new Location("point A");
            locationA.setLatitude(Double.parseDouble(coords.get(i)[1]));
            locationA.setLongitude(Double.parseDouble(coords.get(i)[0]));

            Location locationB = new Location("point B");
            locationB.setLatitude(Double.parseDouble(coords.get(i+1)[1]));
            locationB.setLongitude(Double.parseDouble(coords.get(i+1)[0]));  

            String str = locationA.distanceTo(locationB)/1000+"";

            //Оставляем 2 цифры после запятой
            if (str.length() > str.indexOf(".") + 2){
                str = str.substring(0, str.indexOf(".") + 2);
            }
            str = str + " km";
            distances[i] = str;
        }

        return true;
    }

    @Override
    protected boolean isRouteDisplayed() {
        return true;
    }
}


//**********************************
//Листинг DirectionPathOverlay.java
//**********************************

package com.evtgroup.dd;

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 DirectionPathOverlay extends Overlay {

    private GeoPoint gp1;
    private GeoPoint gp2;

    public DirectionPathOverlay(GeoPoint gp1, GeoPoint gp2) {
        this.gp1 = gp1;
        this.gp2 = gp2;
    }

    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);
            paint.setColor(Color.RED);
            Point point2 = new Point();
            projection.toPixels(gp2, point2);
            paint.setStrokeWidth(4);
            canvas.drawLine((float)point.x, (float)point.y, (float)point2.x, (float)point2.y, paint);
        }
        return super.draw(canvas, mapView, shadow, when);
    }
}

Результат:

Метки: , ,

Версия для печати

Оставить комментарий

Вы должны войти для комментирования.