Te warsztaty są częścią kursu Zaawansowany Android w Kotlinie. Najwięcej korzyści z tego kursu uzyskasz, jeśli przejdziesz wszystkie ćwiczenia w kolejności, ale nie jest to obowiązkowe. Wszystkie ćwiczenia z tego kursu znajdziesz na stronie docelowej ćwiczeń z zaawansowanego Androida w Kotlinie.
Tworzenie aplikacji z Mapami Google umożliwia dodawanie do nich funkcji takich jak zdjęcia satelitarne, zaawansowane elementy sterujące interfejsu map, śledzenie lokalizacji i znaczniki lokalizacji. Możesz wzbogacić standardowe Mapy Google, wyświetlając informacje z własnego zbioru danych, np. lokalizacje znanych miejsc do wędkowania lub wspinaczki. Możesz też tworzyć gry, w których gracz eksploruje świat fizyczny, np. w poszukiwaniu skarbów lub w grach w rzeczywistości rozszerzonej.
W tej lekcji utworzysz aplikację Mapy Google o nazwie Wander, która wyświetla dostosowane mapy i lokalizację użytkownika.
Wymagania wstępne
Znajomość tych zagadnień:
- Jak utworzyć podstawową aplikację na Androida i uruchomić ją w Android Studio.
- Jak tworzyć zasoby, np. ciągi znaków, i nimi zarządzać.
- Jak refaktoryzować kod i zmieniać nazwy zmiennych za pomocą Android Studio.
- Jak korzystać z Map Google jako użytkownik.
- Jak ustawić uprawnienia czasu działania.
Czego się nauczysz
- Jak uzyskać klucz interfejsu API w Konsoli interfejsów API Google i zarejestrować go w aplikacji
- Jak zintegrować mapę Google z aplikacją
- Jak wyświetlać różne typy map
- Jak dostosować styl mapy Google
- Dodawanie znaczników do mapy
- Jak umożliwić użytkownikowi umieszczenie znacznika w interesującym miejscu
- Włączanie śledzenia lokalizacji
- Jak utworzyć aplikację
Wander
z osadzoną Mapą Google - Jak tworzyć niestandardowe funkcje aplikacji, takie jak znaczniki i style
- Jak włączyć śledzenie lokalizacji w aplikacji
W tym laboratorium kodowania utworzysz aplikację Wander
, która wyświetla mapę Google z niestandardowym stylem. Aplikacja Wander umożliwia umieszczanie znaczników w lokalizacjach, dodawanie nakładek i wyświetlanie swojej lokalizacji w czasie rzeczywistym.
Pakiet Maps SDK na Androida wymaga klucza API. Aby uzyskać klucz interfejsu API, zarejestruj projekt na stronie Interfejsy API i usługi. Klucz interfejsu API jest powiązany z certyfikatem cyfrowym, który łączy aplikację z jej autorem. Więcej informacji o używaniu certyfikatów cyfrowych i podpisywaniu aplikacji znajdziesz w artykule Podpisywanie aplikacji.
W tym ćwiczeniu z programowania użyjesz klucza interfejsu API dla certyfikatu debugowania. Certyfikat debugowania jest z założenia niezabezpieczony, co opisano w artykule Podpisywanie kompilacji debugowania. Opublikowane aplikacje na Androida, które korzystają z pakietu Maps SDK na Androida, wymagają drugiego klucza API: klucza certyfikatu wersji. Więcej informacji o uzyskiwaniu certyfikatu wersji znajdziesz w artykule Uzyskiwanie klucza interfejsu API.
Android Studio zawiera szablon aktywności w Mapach Google, który generuje przydatny kod szablonu. Kod szablonu zawiera plik google_maps_api.xml z linkiem, który ułatwia uzyskanie klucza interfejsu API.
Krok 1. Utwórz projekt Wander za pomocą szablonu map
- Utwórz nowy projekt Android Studio.
- Wybierz szablon Aktywność w Mapach Google.
- Nazwij projekt
Wander
. - Ustaw minimalny poziom interfejsu API na API 19. Upewnij się, że język to Kotlin.
- Kliknij Zakończ.
- Gdy aplikacja zostanie utworzona, przejrzyj projekt i te pliki związane z mapami, które Android Studio utworzy za Ciebie:
google_maps_api.xml – ten plik konfiguracyjny służy do przechowywania klucza interfejsu API. Szablon generuje 2 pliki google_maps_api.xml: jeden do debugowania, a drugi do wersji. Plik klucza interfejsu API dla certyfikatu debugowania znajduje się w folderze src/debug/res/values. Plik klucza interfejsu API dla certyfikatu wersji znajduje się w katalogu src/release/res/values. W tym module użyjesz tylko certyfikatu debugowania.
activity_maps.xml – ten plik układu zawiera pojedynczy fragment, który wypełnia cały ekran. Klasa SupportMapFragment
jest podklasą klasy Fragment
. SupportMapFragment
to najprostszy sposób na umieszczenie mapy w aplikacji. Jest to otoczka widoku mapy, która automatycznie obsługuje niezbędne potrzeby związane z cyklem życia.
Możesz umieścić SupportMapFragment
w pliku układu za pomocą tagu <fragment>
w dowolnym tagu ViewGroup
z dodatkowym atrybutem name
.
android:name="com.google.android.gms.maps.SupportMapFragment"
MapsActivity.java – plik MapsActivity.kt tworzy instancję SupportMapFragment
w metodzie onCreate()
i używa klasy getMapAsync
()
do automatycznego inicjowania systemu map i widoku. Aktywność zawierająca element SupportMapFragment
musi implementować interfejs OnMapReadyCallback
i jego metodę onMapReady()
. Metoda onMapReady()
jest wywoływana po wczytaniu mapy.
Krok 2. Uzyskaj klucz interfejsu API
- Otwórz wersję debugowania pliku google_maps_api.xml.
- W pliku poszukaj komentarza z długim adresem URL. Parametry adresu URL zawierają szczegółowe informacje o Twojej aplikacji.
- Skopiuj adres URL i wklej go w przeglądarce.
- Postępuj zgodnie z instrukcjami, aby utworzyć projekt na stronie Interfejsy API i usługi. Dzięki parametrom w podanym adresie URL strona wie, że ma automatycznie włączyć pakiet Maps SDK na Androida.
- Kliknij Utwórz klucz interfejsu API.
- Na następnej stronie otwórz sekcję Klucze interfejsu API i kliknij utworzony przed chwilą klucz.
- Kliknij Ogranicz klucz i wybierz Maps SDK na Androida, aby ograniczyć użycie klucza do aplikacji na Androida.
- Skopiuj wygenerowany klucz interfejsu API. Zaczyna się od „
AIza"
”. - W pliku
google_maps_api.xml
wklej klucz do ciągu znakówgoogle_maps_key
w miejscu, w którym znajduje się tekstYOUR_KEY_HERE
. - Uruchom aplikację. W aktywności powinna być widoczna osadzona mapa ze znacznikiem ustawionym w Sydney w Australii. (Znacznik Sydney jest częścią szablonu i możesz go później zmienić).
Krok 3. Zmień nazwę mMap
MapsActivity
ma prywatny lateinit
var
o nazwie mMap
, który jest typu GoogleMap
. Aby zachować zgodność z konwencjami nazewnictwa w języku Kotlin, zmień nazwę mMap
na map
.
- W
MapsActivity
kliknij prawym przyciskiem myszymMap
i kliknij Refaktoryzacja> Zmień nazwę...
- Zmień nazwę zmiennej na
map
.
Zwróć uwagę, że wszystkie odwołania do mMap
w funkcji onMapReady()
również zmieniają się na map
.
Mapy Google obejmują kilka typów map: normalną, hybrydową, satelitarną, terenu i „brak” (bez mapy).
Normalna mapa | Mapa satelitarna | Mapa hybrydowa | Mapa terenu |
Każdy typ mapy zawiera inne informacje. Na przykład podczas korzystania z map w nawigacji samochodowej przydatne jest wyświetlanie nazw ulic, więc możesz użyć opcji normalnej. Podczas wędrówki mapa terenu może pomóc Ci określić, ile jeszcze musisz się wspinać, aby dotrzeć na szczyt.
W tym zadaniu:
- Dodaj pasek aplikacji z menu opcji, które umożliwia użytkownikowi zmianę typu mapy.
- Przesuń początkową lokalizację mapy do lokalizacji swojego domu.
- Dodaj obsługę znaczników, które wskazują pojedyncze lokalizacje na mapie i mogą zawierać etykietę.
Dodawanie menu typów map
W tym kroku dodasz pasek aplikacji z menu opcji, które umożliwia użytkownikowi zmianę typu mapy.
- Aby utworzyć nowy plik XML menu, kliknij prawym przyciskiem myszy katalog res i wybierz New (Nowy) > Android Resource File (Plik zasobów Androida).
- W oknie nadaj plikowi nazwę
map_options
. - Jako typ zasobu wybierz Menu.
- Kliknij OK.
- Na karcie Kod zastąp kod w nowym pliku tym kodem, aby utworzyć opcje menu mapy. Typ mapy „brak” został pominięty, ponieważ w jego przypadku nie wyświetla się żadna mapa. Ten krok spowoduje błąd, ale w następnym kroku go rozwiążesz.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/normal_map"
android:title="@string/normal_map"
app:showAsAction="never" />
<item
android:id="@+id/hybrid_map"
android:title="@string/hybrid_map"
app:showAsAction="never" />
<item
android:id="@+id/satellite_map"
android:title="@string/satellite_map"
app:showAsAction="never" />
<item
android:id="@+id/terrain_map"
android:title="@string/terrain_map"
app:showAsAction="never" />
</menu>
- W sekcji
strings.xml
dodaj zasoby dla atrybutówtitle
, aby rozwiązać błędy.
<resources>
...
<string name="normal_map">Normal Map</string>
<string name="hybrid_map">Hybrid Map</string>
<string name="satellite_map">Satellite Map</string>
<string name="terrain_map">Terrain Map</string>
<string name="lat_long_snippet">Lat: %1$.5f, Long: %2$.5f</string>
<string name="dropped_pin">Dropped Pin</string>
<string name="poi">poi</string>
</resources>
- W
MapsActivity
zastąp metodęonCreateOptionsMenu()
i rozwiń menu z pliku zasobumap_options
.
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.map_options, menu)
return true
}
- W
MapsActivity.kt
zastąp metodęonOptionsItemSelected()
. Zmień typ mapy za pomocą stałych typu mapy, aby odzwierciedlić wybór użytkownika.
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
// Change the map type based on the user's selection.
R.id.normal_map -> {
map.mapType = GoogleMap.MAP_TYPE_NORMAL
true
}
R.id.hybrid_map -> {
map.mapType = GoogleMap.MAP_TYPE_HYBRID
true
}
R.id.satellite_map -> {
map.mapType = GoogleMap.MAP_TYPE_SATELLITE
true
}
R.id.terrain_map -> {
map.mapType = GoogleMap.MAP_TYPE_TERRAIN
true
}
else -> super.onOptionsItemSelected(item)
}
- Uruchom aplikację.
- Kliknij
, aby zmienić typ mapy. Zwróć uwagę, jak wygląd mapy zmienia się w różnych trybach.
Domyślnie wywołanie zwrotne onMapReady()
zawiera kod, który umieszcza znacznik w Sydney w Australii, gdzie powstały Mapy Google. Domyślne wywołanie zwrotne animuje też mapę, aby przesunąć ją do Sydney.
W tym zadaniu sprawisz, że kamera mapy przesunie się do Twojego domu, powiększy obraz do określonego poziomu i umieści tam znacznik.
Krok 1. Powiększ widok domu i dodaj znacznik
- W pliku
MapsActivity.kt
znajdź metodęonMapReady()
. Usuń z niego kod, który umieszcza znacznik w Sydney i przesuwa kamerę. Twoja metoda powinna teraz wyglądać tak:
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
}
- Aby znaleźć szerokość i długość geograficzną swojego domu, wykonaj te czynności.
- Utwórz wartość szerokości i długości geograficznej, a następnie wpisz ich wartości zmiennoprzecinkowe.
val latitude = 37.422160
val longitude = -122.084270
- Utwórz nowy obiekt
LatLng
o nazwiehomeLatLng
. W obiekciehomeLatLng
przekaż utworzone przed chwilą wartości.
val homeLatLng = LatLng(latitude, longitude)
- Utwórz
val
, aby określić, jak bardzo chcesz powiększyć mapę. Użyj poziomu powiększenia 15f.
val zoomLevel = 15f
Poziom powiększenia określa, jak bardzo powiększona jest mapa. Poniższa lista pokazuje przybliżony poziom szczegółowości na poszczególnych poziomach powiększenia:
1
: świat5
: ląd/kontynent10
: miasto15
: ulice20
: budynki,
- Przesuń kamerę do pozycji
homeLatLng
, wywołując funkcjęmoveCamera()
na obiekciemap
i przekazując obiektCameraUpdate
za pomocąCameraUpdateFactory.newLatLngZoom()
. Przekaż obiekthomeLatLng
izoomLevel
.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
- Dodaj znacznik do mapy w punkcie
homeLatLng
.
map.addMarker(MarkerOptions().position(homeLatLng))
Ostateczna metoda powinna wyglądać tak:
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
//These coordinates represent the latitude and longitude of the Googleplex.
val latitude = 37.422160
val longitude = -122.084270
val zoomLevel = 15f
val homeLatLng = LatLng(latitude, longitude)
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
map.addMarker(MarkerOptions().position(homeLatLng))
}
- Uruchom aplikację. Mapa powinna przesunąć się do Twojego domu, powiększyć do wybranego poziomu i umieścić na nim znacznik.
Krok 2. Zezwól użytkownikom na dodawanie znacznika za pomocą długiego kliknięcia
W tym kroku dodasz znacznik, gdy użytkownik naciśnie i przytrzyma lokalizację na mapie.
- Utwórz w pliku
MapsActivity
metodęsetMapLongClick()
, która przyjmuje argumentGoogleMap
. - Dołącz
setOnMapLongClickListener
do obiektu mapy.
private fun setMapLongClick(map:GoogleMap) {
map.setOnMapLongClickListener { }
}
- W
setOnMapLongClickListener()
wywołaj metodęaddMarker()
. Przekaż nowy obiektMarkerOptions
z ustawioną pozycją na przekazaną wartośćLatLng
.
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
map.addMarker(
MarkerOptions()
.position(latLng)
)
}
}
- Na końcu metody
onMapReady()
wywołaj funkcjęsetMapLongClick()
z argumentemmap
.
override fun onMapReady(googleMap: GoogleMap) {
...
setMapLongClick(map)
}
- Uruchom aplikację.
- Naciśnij i przytrzymaj mapę, aby umieścić w danym miejscu znacznik.
- Kliknij znacznik, aby wyśrodkować go na ekranie.
Krok 3. Dodaj okno informacji do znacznika
W tym kroku dodasz InfoWindow
, który wyświetla współrzędne znacznika po kliknięciu znacznika.
- W usłudze
setMapLongClick()setOnMapLongClickListener()
utwórzval
dlasnippet
. Fragment to dodatkowy tekst wyświetlany po tytule. W wyświetlanym fragmencie kodu zobaczysz szerokość i długość geograficzną znacznika.
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
// A snippet is additional text that's displayed after the title.
val snippet = String.format(
Locale.getDefault(),
"Lat: %1$.5f, Long: %2$.5f",
latLng.latitude,
latLng.longitude
)
map.addMarker(
MarkerOptions()
.position(latLng)
)
}
}
- W
addMarker()
ustawtitle
znacznika na „Dropped Pin” (Przypięty punkt) za pomocą zasobu ciągu znakówR.string.
dropped_pin
. - Ustaw wartość
snippet
znacznika nasnippet
.
Gotowa funkcja wygląda tak:
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
// A Snippet is Additional text that's displayed below the title.
val snippet = String.format(
Locale.getDefault(),
"Lat: %1$.5f, Long: %2$.5f",
latLng.latitude,
latLng.longitude
)
map.addMarker(
MarkerOptions()
.position(latLng)
.title(getString(R.string.dropped_pin))
.snippet(snippet)
)
}
}
- Uruchom aplikację.
- Kliknij i przytrzymaj mapę, aby umieścić na niej znacznik lokalizacji.
- Kliknij znacznik, aby wyświetlić okno informacji.
Krok 4. Dodaj odbiornik POI
Domyślnie na mapie wyświetlają się ciekawe miejsca wraz z odpowiadającymi im ikonami. Obejmują one m.in. parki, szkoły i budynki rządowe. Gdy typ mapy jest ustawiony na normal
, na mapie pojawiają się też punkty POI firm. Punkty POI firm reprezentują firmy, takie jak sklepy, restauracje i hotele.
W tym kroku dodasz do mapy GoogleMap.OnPoiClickListener
. Ten detektor kliknięć umieszcza znacznik na mapie natychmiast po kliknięciu przez użytkownika punktu POI. Odbiornik kliknięć wyświetla też okno informacyjne zawierające nazwę punktu POI.
- Utwórz w pliku
MapsActivity
metodęsetPoiClick()
, która przyjmuje argumentGoogleMap
. - W metodzie
setPoiClick()
ustawOnPoiClickListener
na przekazanymGoogleMap
.
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
}
}
- W
setOnPoiClickListener()
utwórzval poiMarker
dla znacznika . - Ustaw go na znacznik za pomocą funkcji
map.addMarker()
, gdzieMarkerOptions
ustawiatitle
na nazwę ciekawego miejsca.
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
val poiMarker = map.addMarker(
MarkerOptions()
.position(poi.latLng)
.title(poi.name)
)
}
}
- W funkcji
setOnPoiClickListener()
wywołajshowInfoWindow()
wpoiMarker
, aby natychmiast wyświetlić okno informacji.
poiMarker.showInfoWindow()
Ostateczny kod funkcji setPoiClick()
powinien wyglądać tak.
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
val poiMarker = map.addMarker(
MarkerOptions()
.position(poi.latLng)
.title(poi.name)
)
poiMarker.showInfoWindow()
}
}
- Na końcu pliku
onMapReady()
wywołaj funkcjęsetPoiClick()
i przekaż do niej wartośćmap
.
override fun onMapReady(googleMap: GoogleMap) {
...
setPoiClick(map)
}
- Uruchom aplikację i znajdź punkt POI, np. park lub kawiarnię.
- Kliknij punkt POI, aby umieścić na nim znacznik i wyświetlić jego nazwę w okienku informacyjnym.
Mapy Google możesz dostosowywać na wiele sposobów, nadając im niepowtarzalny wygląd.
Obiekt MapFragment
możesz dostosować za pomocą dostępnych atrybutów XML, tak jak każdy inny fragment. W tym kroku dostosujesz jednak wygląd i styl treści elementu MapFragment
za pomocą metod obiektu GoogleMap
.
Aby utworzyć dostosowany styl mapy, wygeneruj plik JSON, który określa sposób wyświetlania elementów na mapie. Nie musisz tworzyć tego pliku JSON ręcznie. Google udostępnia kreator stylów Google Maps Platform, który generuje plik JSON po wizualnym dostosowaniu mapy. W tym zadaniu zastosujesz na mapie styl retro, co oznacza, że mapa będzie używać kolorów w stylu vintage, a drogi będą kolorowe.
Krok 1. Utwórz styl mapy
- Otwórz w przeglądarce stronę https://mapstyle.withgoogle.com/.
- Kliknij Utwórz styl.
- Kliknij Retro.
- Kliknij Więcej opcji.
- Na liście Typ funkcji wybierz Droga> Wypełnienie.
- Zmień kolor dróg na dowolny kolor (np. różowy).
- Kliknij Zakończ.
- Skopiuj kod JSON z wyświetlonego okna i w razie potrzeby zapisz go w notatniku w formacie zwykłego tekstu, aby użyć go w następnym kroku.
Krok 2. Dodaj styl do mapy
- W Android Studio w katalogu
res
utwórz katalog zasobów i nadaj mu nazwęraw
. Zasoby kataloguraw
są używane jako kod JSON. - Utwórz w katalogu
res/raw
plik o nazwiemap_style.json
. - Wklej zapisany kod JSON do nowego pliku zasobu.
- W
MapsActivity
utwórz zmienną klasyTAG
powyżej metodyonCreate()
. Jest to używane do celów rejestrowania.
private val TAG = MapsActivity::class.java.simpleName
- W pliku
MapsActivity
utwórz też funkcjęsetMapStyle()
, która przyjmuje argumentGoogleMap
. - W
setMapStyle()
dodaj bloktry{}
. - W bloku
try{}
utwórzval success
, aby sprawdzić, czy stylizacja się powiodła. (Dodaj ten blok catch). - W bloku
try{}
ustaw styl JSON na mapę, wywołajsetMapStyle()
na obiekcieGoogleMap
. Przekaż obiektMapStyleOptions
, który wczytuje plik JSON. - Przypisz wynik do zmiennej
success
. MetodasetMapStyle()
zwraca wartość logiczną wskazującą stan powodzenia analizy pliku stylu i ustawienia stylu.
private fun setMapStyle(map: GoogleMap) {
try {
// Customize the styling of the base map using a JSON object defined
// in a raw resource file.
val success = map.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
this,
R.raw.map_style
)
)
}
}
- Dodaj instrukcję warunkową dla wartości
success
równej false. Jeśli stylizacja się nie powiedzie, wydrukuj dziennik z informacją o niepowodzeniu analizy.
private fun setMapStyle(map: GoogleMap) {
try {
...
if (!success) {
Log.e(TAG, "Style parsing failed.")
}
}
}
- Dodaj blok
catch{}
, aby obsłużyć sytuację, w której brakuje pliku stylu. Jeśli w blokucatch
nie można wczytać pliku, zgłoś błądResources.NotFoundException
.
private fun setMapStyle(map: GoogleMap) {
try {
...
} catch (e: Resources.NotFoundException) {
Log.e(TAG, "Can't find style. Error: ", e)
}
}
Gotowa metoda powinna wyglądać tak:
private fun setMapStyle(map: GoogleMap) {
try {
// Customize the styling of the base map using a JSON object defined
// in a raw resource file.
val success = map.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
this,
R.raw.map_style
)
)
if (!success) {
Log.e(TAG, "Style parsing failed.")
}
} catch (e: Resources.NotFoundException) {
Log.e(TAG, "Can't find style. Error: ", e)
}
}
- Na koniec wywołaj metodę
setMapStyle()
w metodzieonMapReady()
, przekazując do niej obiektGoogleMap
.
override fun onMapReady(googleMap: GoogleMap) {
...
setMapStyle(map)
}
- Uruchom aplikację.
- Ustaw mapę w trybie
normal
. Nowy styl powinien być widoczny z motywem retro i drogami w wybranym kolorze.
Krok 3. Nadaj znacznikowi styl
Możesz jeszcze bardziej spersonalizować mapę, dostosowując styl znaczników. W tym kroku zmienisz domyślne czerwone znaczniki na coś bardziej atrakcyjnego.
- W metodzie
onMapLongClick()
dodaj ten wiersz kodu doMarkerOptions()
konstruktora, aby użyć domyślnego znacznika, ale zmienić jego kolor na niebieski.
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
Teraz onMapLongClickListener()
wygląda tak:
map.setOnMapLongClickListener { latLng ->
// A snippet is additional text that's displayed after the title.
val snippet = String.format(
Locale.getDefault(),
"Lat: %1$.5f, Long: %2$.5f",
latLng.latitude,
latLng.longitude
)
map.addMarker(
MarkerOptions()
.position(latLng)
.title(getString(R.string.dropped_pin))
.snippet(snippet)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
)
}
- Uruchom aplikację. Markery, które pojawią się po długim kliknięciu, będą teraz niebieskie. Zwróć uwagę, że markery POI są nadal czerwone, ponieważ nie dodano stylu do metody
onPoiClick()
.
Jednym ze sposobów dostosowania mapy Google jest rysowanie na niej. Ta technika jest przydatna, jeśli chcesz wyróżnić określony typ lokalizacji, np. popularne miejsca do wędkowania.
- Kształty: do mapy możesz dodawać polilinie, wielokąty i okręgi.
GroundOverlay
obiekty: nakładka na teren to obraz przymocowany do mapy. W przeciwieństwie do znaczników nakładki na ziemi są zorientowane na powierzchnię Ziemi, a nie na ekran. Obracanie, pochylanie lub powiększanie mapy zmienia orientację obrazu. Nakładki na ziemię są przydatne, gdy chcesz umieścić pojedynczy obraz w jednym obszarze na mapie.
Krok: dodawanie nakładki na ziemię
W tym zadaniu dodasz nakładkę na ziemię w kształcie Androida w lokalizacji swojego domu.
- Pobierz ten obraz Androida i zapisz go w folderze
res/drawable
. (Upewnij się, że plik ma nazwęandroid.png
).
- W
onMapReady()
po wywołaniu funkcji przenoszącej kamerę do pozycji w domu utwórz obiektGroundOverlayOptions
. - Przypisz obiekt do zmiennej o nazwie
androidOverlay
.
val androidOverlay = GroundOverlayOptions()
- Użyj metody
BitmapDescriptorFactory.fromResource()
, aby utworzyć obiektBitmapDescriptor
z pobranego zasobu obrazu. - Przekaż wynikowy obiekt
BitmapDescriptor
do metodyimage()
obiektuGroundOverlayOptions
.
val androidOverlay = GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.android))
- Utwórz
float overlaySize
dla szerokości w metrach żądanej nakładki. W tym przykładzie dobrze sprawdzi się szerokość100f
.
Ustaw właściwość position
obiektu GroundOverlayOptions
, wywołując metodę position()
, i przekaż obiekt homeLatLng
oraz overlaySize
.
val overlaySize = 100f
val androidOverlay = GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.android))
.position(homeLatLng, overlaySize)
- Wywołaj funkcję
addGroundOverlay()
na obiekcieGoogleMap
i przekaż obiektGroundOverlayOptions
.
map.addGroundOverlay(androidOverlay)
- Uruchom aplikację.
- Zmień wartość
zoomLevel
na 18f, aby wyświetlić obraz Androida jako nakładkę.
Użytkownicy często korzystają z Map Google, aby sprawdzić swoją bieżącą lokalizację. Aby wyświetlić lokalizację urządzenia na mapie, możesz użyć warstwy danych o lokalizacji.
Warstwa danych o lokalizacji dodaje do mapy Moją lokalizację. Gdy użytkownik kliknie przycisk, mapa wyśrodkuje się na lokalizacji urządzenia. Lokalizacja jest wyświetlana jako niebieski punkt, jeśli urządzenie jest nieruchome, a jako niebieski szewron, jeśli się porusza.
W tym zadaniu włączysz warstwę danych o lokalizacji.
Krok: poproś o dostęp do lokalizacji
Włączenie śledzenia lokalizacji w Mapach Google wymaga tylko 1 wiersza kodu. Musisz jednak upewnić się, że użytkownik przyznał uprawnienia do lokalizacji (za pomocą modelu uprawnień w czasie działania).
W tym kroku poproś o dostęp do lokalizacji i włącz śledzenie lokalizacji.
- W pliku
AndroidManifest.xml
sprawdź, czy uprawnienieFINE_LOCATION
jest już obecne. Android Studio wstawiło to uprawnienie, gdy wybrano szablon Map Google.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- W
MapsActivity
utwórz zmienną klasyREQUEST_LOCATION_PERMISSION
.
private val REQUEST_LOCATION_PERMISSION = 1
- Aby sprawdzić, czy uprawnienia zostały przyznane, utwórz w
MapsActivity
metodę o nazwieisPermissionGranted()
. W tej metodzie sprawdź, czy użytkownik przyznał uprawnienia.
private fun isPermissionGranted() : Boolean {
return ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
- Aby włączyć śledzenie lokalizacji w aplikacji, utwórz w
MapsActivity
metodę o nazwieenableMyLocation()
, która nie przyjmuje argumentów i niczego nie zwraca. Sprawdź, czy jest tam uprawnienieACCESS_FINE_LOCATION
. Jeśli uprawnienia zostały przyznane, włącz warstwę lokalizacji. W przeciwnym razie poproś o uprawnienia.
private fun enableMyLocation() {
if (isPermissionGranted()) {
map.isMyLocationEnabled = true
}
else {
ActivityCompat.requestPermissions(
this,
arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION_PERMISSION
)
}
}
- Wywołaj funkcję
enableMyLocation()
z wywołania zwrotnegoonMapReady()
, aby włączyć warstwę lokalizacji.
override fun onMapReady(googleMap: GoogleMap) {
...
enableMyLocation()
}
- Zastąp metodę
onRequestPermissionsResult()
. JeślirequestCode
jest równeREQUEST_LOCATION_PERMISSION
, przyznano uprawnienia, a tablicagrantResults
nie jest pusta i w pierwszym slocie zawieraPackageManager.PERMISSION_GRANTED
, wywołajenableMyLocation()
.
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray) {
if (requestCode == REQUEST_LOCATION_PERMISSION) {
if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
enableMyLocation()
}
}
}
- Uruchom aplikację. Powinno pojawić się okno z prośbą o dostęp do lokalizacji urządzenia. Przyznaj uprawnienia.
Na mapie pojawi się teraz bieżąca lokalizacja urządzenia oznaczona niebieską kropką. Zwróć uwagę na przycisk lokalizacji. Jeśli odsuniesz mapę od swojej lokalizacji i klikniesz ten przycisk, mapa wróci do lokalizacji urządzenia.
Pobierz kod ukończonego ćwiczenia.
$ git clone https://github.com/googlecodelabs/android-kotlin-geo-maps
Możesz też pobrać repozytorium jako plik ZIP, rozpakować go i otworzyć w Android Studio.
- Aby korzystać z interfejsu Maps API, musisz mieć klucz interfejsu API z Konsoli interfejsów API Google.
- W Android Studio użycie szablonu aktywności Map Google generuje element
Activity
z jednym elementemSupportMapFragment
w układzie aplikacji. Szablon dodaje też do manifestu aplikacji elementACCESS_FINE_PERMISSION
, implementuje w aktywności elementOnMapReadyCallback
i zastępuje wymaganą metodęonMapReady()
.
Aby zmienić typ mapy GoogleMap
w czasie działania programu, użyj metody GoogleMap.setMapType()
. Mapa Google może być jednego z tych typów:
- Normalna: typowa mapa drogowa. Pokazuje drogi, niektóre obiekty stworzone przez człowieka i ważne elementy naturalne, takie jak rzeki. Widoczne są też etykiety dróg i obiektów.
- Hybrydowa: dane ze zdjęć satelitarnych z dodatkiem map drogowych. Widoczne są też etykiety dróg i obiektów.
- Satelita: dane fotograficzne. Etykiety dróg i obiektów nie są widoczne.
- Teren: dane topograficzne. Mapa zawiera kolory, poziomice i etykiety oraz cieniowanie perspektywiczne. Widoczne są też niektóre drogi i etykiety.
- Brak: brak kafelków mapy bazowej.
Informacje o Mapach Google:
- Znacznik to wskaźnik konkretnej lokalizacji geograficznej.
- Po kliknięciu znacznika domyślnie wyświetla się okno informacyjne z informacjami o lokalizacji.
- Domyślnie ciekawe miejsca są wyświetlane na mapie bazowej wraz z odpowiednimi ikonami. Obejmują one m.in. parki, szkoły i budynki rządowe.
- Dodatkowo ważne miejsca związane z firmami (sklepy, restauracje, hotele itp.) są domyślnie wyświetlane na mapie, gdy typ mapy to
normal
. - Kliknięcia w przypadku POI możesz rejestrować za pomocą
OnPoiClickListener
. - Za pomocą kreatora stylów możesz zmienić wygląd niemal wszystkich elementów Map Google. Kreator stylów generuje plik JSON, który przekazujesz do Mapy Google za pomocą metody
setMapStyle()
. - Możesz dostosować znaczniki, zmieniając domyślny kolor lub zastępując domyślną ikonę znacznika niestandardowym obrazem.
Inne ważne informacje:
- Użyj nakładki na ziemię, aby przypiąć obraz do lokalizacji geograficznej.
- Użyj obiektu
GroundOverlayOptions
, aby określić obraz, jego rozmiar w metrach i pozycję. Przekaż ten obiekt do metodyGoogleMap.addGroundOverlay()
, aby ustawić nakładkę na mapie. - Jeśli Twoja aplikacja ma uprawnienie
ACCESS_FINE_LOCATION
, możesz włączyć śledzenie lokalizacji, ustawiając wartośćmap.isMyLocationEnabled = true
. - Nie jest to omówione w tym laboratorium, ale możesz podać dodatkowe informacje o lokalizacji, korzystając z Google Street View, czyli interaktywnego zdjęcia panoramicznego danej lokalizacji.
Dokumentacja dla deweloperów aplikacji na Androida:
- Rozpocznij
- Dodawanie mapy ze znacznikiem
- Obiekty mapy
- Dodawanie mapy stylizowanej
- Street View
- Obrazy na powierzchni
Dokumentacja:
Linki do innych ćwiczeń z tego kursu znajdziesz na stronie docelowej ćwiczeń z zaawansowanego Androida w Kotlinie.