Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

12
Indianin na szlaku, czyli o wykorzystaniu Google Maps z Apache Wicket słów kilka. Autor: Grzegorz Musiał 1. Wprowadzenie W czasach kiedy samochód pozbawiony nawigacji GPS jest już odosobnionym wyjątkiem nawet na polskich drogach. W czasach gdy człowiek zapomina jak korzystać z map tradycyjnych. I wreszcie w czasach, w których nieodpłatnie udostępniane są interaktywne mapy, nie sposób stworzyć firmowej strony internetowej, która nie zaznacza dynamicznie adresu siedziby. Podążając tym tokiem rozumowania należy stwierdzić, że zatem nie sposób się obejść bez map, a dokładnie omawianych w niniejszym dokumencie map dostarczanych przez firmę Google, w większości profesjonalnych (firmowych) zastosowań aplikacji webowych. Zatem o ile zastosowanie wspomnianego gotowego rozwiązania na statycznych stronach HTML z wykorzystaniem dostarczonego kodu Java Script, nie nastręcza żadnych problemów. O tyle zastosowanie rozwiązania Google’a niestety wymaga większych i bardziej skomplikowanych zabiegów w przypadku chęci zastosowania jednym z najmłodszych dzieci w rodzinie frameworków Java EE – Apache Wicket. Całe szczęście z pomocą przychodzi nam szerokie grono internautów i pasjonatów programowania, które na stronie [1] udostępniło gotową bibliotekę implementującą Java Scriptowy kod Google Maps. Biblioteka ta nosi nazwę wicket-contrib-gmap2 i opiera się na co prawda nie najnowszym kodzie, bo w wersji drugiej (obecnie jest wersja nr 3). Jednakże z uwagi na szerokie stosowanie starszej wersji na większości serwisów WWW, wersja trzecia dopiero zyskuje sobie zwolenników i zapewne niedługo doczekamy się również wicket- contrib-gmap3. Póki co, skupimy się na dostępnej na wspomnianej stronie, aktualnej wersji. 2. Przygotowanie środowiska 2.1. Uzyskanie klucza W celu używania Google Maps API poza serwerem lokalnym, tj. http://localhost/ , konieczne jest uzyskanie klucza, który podawany jest w momencie tworzenia obiektu mapy. Aby uzyskać wspomniany klucz, należy wejść na stronę http://code.google.com/intl/pl/apis/maps/documentation/ , na której w prawym górnym rogu wybieramy opcję Signup for an API key.

Transcript of Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

Page 1: Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

Indianin na szlaku, czyli o wykorzystaniu Google Maps z Apache

Wicket słów kilka. Autor: Grzegorz Musiał

1. Wprowadzenie

W czasach kiedy samochód pozbawiony nawigacji GPS jest już odosobnionym wyjątkiem

nawet na polskich drogach. W czasach gdy człowiek zapomina jak korzystać z map

tradycyjnych. I wreszcie w czasach, w których nieodpłatnie udostępniane są

interaktywne mapy, nie sposób stworzyć firmowej strony internetowej, która nie

zaznacza dynamicznie adresu siedziby. Podążając tym tokiem rozumowania należy

stwierdzić, że zatem nie sposób się obejść bez map, a dokładnie omawianych w

niniejszym dokumencie map dostarczanych przez firmę Google, w większości

profesjonalnych (firmowych) zastosowań aplikacji webowych.

Zatem o ile zastosowanie wspomnianego gotowego rozwiązania na statycznych stronach

HTML z wykorzystaniem dostarczonego kodu Java Script, nie nastręcza żadnych

problemów. O tyle zastosowanie rozwiązania Google’a niestety wymaga większych i

bardziej skomplikowanych zabiegów w przypadku chęci zastosowania jednym z

najmłodszych dzieci w rodzinie frameworków Java EE – Apache Wicket. Całe szczęście z

pomocą przychodzi nam szerokie grono internautów i pasjonatów programowania,

które na stronie [1] udostępniło gotową bibliotekę implementującą Java Scriptowy kod

Google Maps. Biblioteka ta nosi nazwę wicket-contrib-gmap2 i opiera się na co prawda

nie najnowszym kodzie, bo w wersji drugiej (obecnie jest wersja nr 3). Jednakże z uwagi

na szerokie stosowanie starszej wersji na większości serwisów WWW, wersja trzecia

dopiero zyskuje sobie zwolenników i zapewne niedługo doczekamy się również wicket-

contrib-gmap3. Póki co, skupimy się na dostępnej na wspomnianej stronie, aktualnej

wersji.

2. Przygotowanie środowiska

2.1. Uzyskanie klucza

W celu używania Google Maps API poza serwerem lokalnym, tj. http://localhost/ ,

konieczne jest uzyskanie klucza, który podawany jest w momencie tworzenia obiektu

mapy.

Aby uzyskać wspomniany klucz, należy wejść na stronę

http://code.google.com/intl/pl/apis/maps/documentation/ , na której w prawym

górnym rogu wybieramy opcję Signup for an API key.

Page 2: Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

Następnie na wyświetlonej stronie, na samym dole wypełniamy następujący formularz:

Wykonujemy:

• Zaznaczamy checkboxa oznaczającego, że zapoznaliśmy się z warunkami

korzystania z biblioteki,

• Wpisujemy adres naszej strony. Uwaga: warto wpisywać najwyższy poziom

posiadanej domeny, tj. bez WWW, ani pozostałych przedrostków. Zastosowanie

domeny typu http://jakasdomena.pl pozwala później korzystać z tego samego

klucza zarówno na stronie http://poddomena.jakasdomena.pl jak i jakiejkolwiek

innej subdomenie podanej domeny.

Po wysłaniu formularza otrzymujemy w odpowiedzi poniższą stronę:

Widzimy na samej górze wygenerowany API Key i tylko on nas interesuje. Dostępne

poniżej przykłady w Java Script’cie nie są użyteczne z punktu widzenia Wicketa.

Page 3: Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

2.2. Zainstalowanie wicket-contrib-gmap2 w repozytorium Maven’a

Przed przystąpieniem do napisania pierwszego kodu wykorzystującego Mapy Google,

należy zainstalować wspomnianą bibliotekę w repozytorium Mavena. W tym celu ze

strony [1] pobieramy z SVN projektu najnowszą wersją biblioteki (na dzień 10.01.2010r.

1.4.0). W folderze do którego chekout’ujemy pobrane pliki, wchodzimy do folderu

gmap2-parent a następnie do folderu gmap2. Z linii komend uruchamiamy następnie:

mvn install

Po otrzymaniu komunikatu BUILD SUCCESSFUL możemy przystąpić do napisania

pierwszego kodu.

Zanim jednak kod JAVY musimy jeszcze dopisać poniższy kod w sekcji <dependencies>

pliku POM.xml naszego projektu:

<dependency>

<groupId>org.wicketstuff</groupId>

<artifactId>gmap2</artifactId>

<version>1.4-SNAPSHOT</version>

</dependency>

3. Wykorzystanie Google Maps w kodzie aplikacji

3.1. Umieszczenie kontrolki mapy na stronie

Wykorzystywana biblioteka zawiera w sobie definicje klasy GMap2. Klasa ta

charakteryzuje się tym, że dziedziczy z klasy nadrzędnej Component, dzięki temu jej

zachowanie w przypadku umieszczania na stronie jest analogicznie do znanych

komponentów, np. Label. Wykorzystując tę analogię oraz pusty projekt utworzony za

pomocą archetypu dostępnego na stronie [4], przedstawimy proste umieszczenie mapy

na stronie WWW.

W tym celu wyczyścimy kod klasa HomePage.java otrzymując poniższy kod:

Następnie analogicznie pozbędziemy się zbędnego kodu przykładowego z pliku

HomePage.html otrzymując:

Page 4: Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

Teraz przejdziemy do najciekawszej części, czyli właściwego umieszczania mapy na

stronie.

W tym celu przygotujemy na stronie HTML odpowiedni kontener. Założymy, że

początkowo nasza mapa ma mieć szerokość 800px a wysokość 400px, co

odzwierciedlimy odpowiednim stylem CSS umieszczonym inline w znaczniku <div>,

który zostanie zagnieżdżony bezpośrednio pomiędzy znacznikami <body>.

Następnie, aby w ogóle kompilacja aplikacji zakończyła się sukcesem, należy dodać

odpowiedni komponent w kodzie JAVY w pliku HomePage.java.

Zauważamy, że w porównaniu do poprzedniej wersji tego pliku pojawiły się dwie nowe

linijki.

• W pierwszej z nich utworzony zostaje obiekt mapy. Jest on wspomnianego wcześniej

typu GMap2. W konstruktorze widzimy dwa parametry:

a. Pierwszy: identyfikator komponentu umieszczanego na stronie, tj. dokładnie

to samo co umieszczono wcześniej w atrybucie wicket:id w pliku HTML.

b. Drugi: wygenerowany wcześniej API Key.

• W drugiej linijce natomiast dokonujemy powiązania stworzonej mapy z widokiem

HTML. W tym momencie potwierdzone zostaje wcześniejsze rozszerzanie przez

klase GMap2 klasy Component, gdyż sygnatura metody add jest następująca:

add(Component c).

Page 5: Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

Tak napisany kod, po wcześniejszym tymczasowym usunięciu klas testowych z aplikacji

archetypowej możemy uruchomić na lokalnym serwerze wykorzystując odpowiedni

goal Maven’owego builda, czyli:

mvn jetty6:run

Oczom naszym ukaże się poniższa strona:

Niestety w tym momencie wyświetlana jest domyślna lokalizacja, a dokładnie Mountain

View, USA. Ale kwestią wyświetlenia żądanego punktu ma mapie zajmiemy się w

kolejnym podpunkcie.

3.2. Zaznaczenie adresu na mapie (współrzędne)

Mając wiedzę i kod stworzony w poprzednim podpunkcie skupimy się teraz na

najbardziej podstawowym dostosowaniu mapy do wymogów klienta i aplikacji, tj.

wyśrodkujemy ją na wybranym przez nas adresie, a pod tym adresem umieścimy

domyślny marker.

Zanim jednak tego dokonamy, w tym podpunkcie będziemy potrzebować konkretnych

współrzędnych punktu na mapie, o którym mowa.

Zatem udamy się na stronę http://maps.google.com i tam w wyszukiwarce podając

Wrocław, Wybrzeże Wyspiańskiego 27 (adres Politechniki Wrocławskiej).

Page 6: Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

Następnie w calu wyłuskania informacji o dokładnych współrzędnych punktu:

• Klikamy lewym przyciskiem na pokazany marker i z podręcznego menu

wybieramy opcję Wyśrodkuj mapę tutaj.

• Klikamy na umieszczony w prawym górnym roku link Link i kopiujemy jego

wartość.

Skopiowany link powinien mieć postać zbliżoną do poniższej:

http://maps.google.com/maps?f=q&source=s_q&hl=pl&geocode=&q=Wro

c%C5%82aw,+wybrze%C5%BCe+wyspia%C5%84skiego+27&sll=37.0625,-

95.677068&sspn=39.184175,93.076172&ie=UTF8&hq=&hnear=wybrze%C5%

BCe+Stanis%C5%82awa+Wyspia%C5%84skiego+27,+Wroc%C5%82aw,+Dolno%

C5%9Bl%C4%85skie,+Polska&ll=51.107739,17.062175&spn=0.007598,0.

022724&z=16

Fragment, który nas interesuje z punktu poszukiwanych współrzędnych wpisanego

adresu, rozpoczyna się sekwencją „&ll=”, po której nastepują rozdzielone przecinkiem

dwie liczby zmiennoprzecinkowe. Jest to odpowiednio: długość i szerokość geograficzna.

Znając ten punkt, przejdziemy do kodu aplikacji i zrealizowania postawionego zadania.

W podpunkcie tym, modyfikacjom będzie ulegać wyłącznie kod HomePage.java gdyż

działać będziemy na kontrolce mapy, a nie na układzie strony. Po modyfikacjach kod

powinien wyglądać następująco:

Page 7: Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

Pierwszą modyfikacją kodu w porównaniu do jego wcześniejszej wersji było dodanie

poniższej linijki:

GLatLng wsp = new GLatLng(51.107739, 17.062175);

Odpowiada ona za utworzenie dostępnego również w bazowym Google Maps API

obiektu „punktu na mapie” a dokładnie pary współrzędnych: długości i szerokości

geograficznej. Jak łatwo zauważyć parametry konstruktora tego obiektu, są dokładnie

wyłuskanymi z wcześniejszego linka liczbami.

W kolejnej linijce:

mapa.setCenter(wsp);

Wykorzystując metodę obiektu GMap2 wyśrodkowaliśmy widok na wspomnianym,

utworzonym powyżej punkcie.

Ostatnim krokiem było utworzenie, wymaganego przez naszego klienta, domyślnego

markera znajdującego się również we wspomnianym punkcie WSP.

GMarker marker = new GMarker(wsp);

Ostatnim krokiem wieńczącym dzieło było dodanie utworzonego markera do mapy. Tym

razem warto zauważyć, że dodawanie nie odbywa się bezpośrednio do ciała strony

HTML przez metodę add, a przy użyciu metody obiektu GMap2 addOverlay.

mapa.addOverlay(marker);

Ostateczny efekt pracy wygląda następująco:

Page 8: Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

Poprzez porównanie do widoku uzyskanego na stronie http://maps.google.com łatwo

zauważyć niedociągnięcia otrzymanej mapy:

• Brak kontroli nad przybliżeniem (sterowania w lewym górnym rogu)

• Zbyt oddalony widok domyślny, tj. ten który użytkownik widzi zaraz po

załadowaniu się mapy.

Aby rozwiązać wspomniane problemy należy wykonać kolejno przedstawione operacje.

Dodanie kontrolki sterującej przybliżenie odbywa się poprzez dodanie następującego

kodu:

mapa.addControl(GControl.GLargeMapControl);

Natomiast przybliżenie mapy najwygodniej dostosować empirycznie wykorzystując

metodę obiekty GMap2 setZoom. W naszym przykładzie zastosujemy:

mapa.setZoom(15);

Ostateczny efekt prac zaprezentowano na poniższym ekranie.

Page 9: Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

Widzimy zatem jak przy pomocy kilku linii kodu łatwo jest wykonać najbardziej

podstawowe zadanie jakie spoczywa na twórcy strony WWW, czyli umieszczenie mapy z

zaznaczonym adresem siedziby firmy.

Nie spoczniemy jednak na laurach i następnym punkcie przejdziemy do bardziej

zaawansowanego rozwiązania, tj. zaznaczymy siedzibę firmy na mapie wykorzystując do

tego wbudowany w Google Maps API mechanizm wyszukiwania adresów na

podstawie frazy wyszukiwania (tak jak pokazano na stronie http://maps.google.com).

3.3. Zaznaczenie adresu na mapie (fraza wyszukiwania)

Nie zawsze mogąc, a przede wszystkim nie zawsze mając czas na przeglądanie strony

maps.google.com, wyłuskiwanie współrzędnych z linków, poszukamy alternatywnego

rozwiązania zaznaczania współrzędnych. Rozwiązanie to oprzemy na wbudowanym w

Google Maps wyszukiwania po frazie i na jego podstawie uzyskiwanie obiektu

współrzędnych GLatLng.

W niniejszym przykładzie wykorzystamy dostępny wraz z używaną biblioteką wicket-

contrib-gmap2 pakiet wicket-contrib-gmap2-examples, w którym umieszczono kod

klasy ServerGeocoder, która odpowiada za wykonywana przez serwer zapytania o

współrzędne kierowane do serwera Google Maps.

import java.io.IOException;

import java.io.Serializable;

import java.net.MalformedURLException;

import java.net.URL;

import java.net.URLConnection;

import org.apache.wicket.util.io.Streams;

import wicket.contrib.gmap.api.GLatLng;

Page 10: Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

import wicket.contrib.gmap.util.Geocoder;

import wicket.contrib.gmap.util.GeocoderException;

/**

* A serverside Geocoder.

*/

public class ServerGeocoder implements Serializable

{

private static final long serialVersionUID = 1L;

// referencja do geocodera

private Geocoder geocoder;

/**

* @param gMapKey

* Gmap API key

* @throws IllegalArgumentException

* If the API key is <code>null</code>

*/

public ServerGeocoder(String gMapKey) {

if (gMapKey == null) {

throw new IllegalArgumentException("API key

cannot be null");

}

this.geocoder = new Geocoder(gMapKey);

}

/**

* @param address

* The address for which a coordinate must be

found.

* @return GLatLng point for the address found by the

Geocoder

* @throws GeocoderException

* If a error happened on the side of Google

* @throws IOException

* If a connection error happened

*/

public GLatLng findAddress(String address) throws

IOException {

URL url = this.getURL(address);

URLConnection connection = url.openConnection();

String content =

Streams.readString(connection.getInputStream());

return geocoder.decode(content);

}

protected URL getURL(String address) throws

MalformedURLException

{

return new URL(geocoder.encode(address));

}

Page 11: Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

}

Wykorzystując powyższą klasę zastąpimy dotychczasowe ręczne tworzenie obiektu wsp,

jego automatyczną wersją będącą wywołaniem metody klasy ServerGeocoder.

Główny kod aplikacji znajduję się teraz w bloku try {} catch, co jest podyktowane

koniecznością reagowania na ewentualny brak wyszukiwanego adresu lub też problemy

komunikacyjne z serwerem.

Widzimy zatem w nowej wersji kodu tworzenie obiektu sg typu ServerGeocoder, w

którego konstruktorze podajemy wykorzystywany już wcześniej API key, a następnie już

we wspomnianym bloku wywołujemy metodę owego obiektu – findAddress, której

przekazujemy dokładnie taka samą frazę wyszukiwania, jak na stronie

http://maps.google.com.

Efekt naszych działań przedstawia poniższy ekran.

Page 12: Indianin na szlaku, czyli o wykorzystaniu Google Maps z ...

Porównując nakład pracy wymagany do naniesienia na mapę poszukiwanego przez nas

adresu można by złudnie dojść do wniosku, że drugi pokazany sposób jest tym

najbardziej słusznym ponieważ wymaga najmniej pracy. Jednak jeżeli weźmiemy pod

uwagę każdorazową konieczność wyszukiwania adresu przy każdym załadowaniu mapy,

i to adresu, który dobrze znamy i który raz wprowadzony nie ulega zmianie, to narzut

spowodowany tym wyszukiwaniem może niekiedy rzutować na czas ładowania strony.

Dlatego w przypadkach kiedy chcemy zaznaczyć na mapie punkt, którego położenie nie

będzie ulegać zmianie, to mimo wszystko lepiej zastosować pierwszy sposób.

4. Podsumowanie

Ten krótki tutotial stanowi tylko niewielki pokaz możliwości Google Maps jako

środowiska do pisania aplikacji wykorzystujących mapy, a tym samym również niewielki

wycinek funkcjonalności dostępnych w bibliotece wicket-contrib-gmap2. Dlatego też

zachęca się Czytelnika do dalszego eksperymentowania.

5. Literatura

[1] http://wicketstuff.org/confluence/display/STUFFWIKI/wicket-contrib-gmap2

[2] http://wicket.apache.org/

[3] http://code.google.com/intl/pl/apis/maps/documentation/

[4] http://wicket.apache.org/quickstart.html