To ćwiczenie programowania jest częścią kursu „Android dla zaawansowanych w Kotlinie”. Korzyści z tego kursu będą dla Ciebie najbardziej wartościowe, jeśli wykonasz je w sekwencjach ćwiczeń z programowania, ale nie jest to obowiązkowe. Wszystkie ćwiczenia z kursu są wymienione na stronie Zaawansowane ćwiczenia z programowania na Androida w Kotlin.
Tworzenie aplikacji w Mapach Google pozwala dodawać do aplikacji funkcje takie jak zdjęcia satelitarne, rozbudowane opcje interfejsu dla map, śledzenie lokalizacji i znaczniki lokalizacji. Możesz dodać wartość do standardowych Map Google, wyświetlając informacje z własnego zbioru danych, np. informacje o lokalizacjach popularnych łowisk lub ścianek wspinaczkowych. Możesz też tworzyć gry, w których gracz musi odkrywać świat fizyczny, np. poszukiwanie skarbów lub gra w rzeczywistości rozszerzonej.
W ramach tej lekcji tworzysz aplikację Mapy Google o nazwie Wander, która wyświetla mapy niestandardowe i pokazuje lokalizację użytkownika.
Wymagania wstępne
Wiedza na temat:
- Jak utworzyć podstawową aplikację na Androida i uruchomić ją w Android Studio.
- jak tworzyć zasoby (np. ciągi tekstowe) i nimi zarządzać;
- Jak refaktoryzować zmienne kodu i zmieniać ich nazwy, korzystając z Androida Studio.
- Jak korzystać z mapy Google jako użytkownika.
- Jak ustawić uprawnienia czasu działania.
Czego się nauczysz
- Jak uzyskać klucz interfejsu API z Konsoli interfejsów API Google i zarejestrować klucz w aplikacji
- Jak zintegrować Mapę Google z aplikacją
- Jak wyświetlać różne typy map
- Styl mapy Google
- Jak dodawać znaczniki do mapy
- Jak zezwolić użytkownikowi na umieszczenie znacznika w ciekawym miejscu (ważnym)
- Jak włączyć śledzenie lokalizacji
- Tworzenie aplikacji
Wander
z wbudowaną Mapą Google - Tworzenie niestandardowych funkcji aplikacji, takich jak znaczniki i styl
- Jak włączyć śledzenie lokalizacji w aplikacji
W ramach tych ćwiczeń tworzysz aplikację Wander
, która wyświetla mapę Google ze spersonalizowanym stylem. Aplikacja Wander umożliwia upuszczanie znaczników na lokalizacje, dodawanie nakładek oraz wyświetlanie lokalizacji w czasie rzeczywistym.
Pakiet SDK dla Map na Androida wymaga klucza interfejsu API. Aby uzyskać klucz interfejsu API, zarejestruj swój projekt na stronie Interfejs API i usługi. Klucz interfejsu API jest powiązany z certyfikatem cyfrowym, który łączy aplikację z autorem. Więcej informacji o używaniu certyfikatów cyfrowych i podpisywaniu aplikacji znajdziesz w artykule Podpisywanie aplikacji.
W tym kursie wykorzystasz klucz interfejsu API certyfikatu debugowania. Zgodnie z opisem w artykule Podpisywanie kompilacji debugowania certyfikat debugowania nie jest bezpieczny. Opublikowane aplikacje na Androida, które używają pakietu SDK Map na Androida, wymagają drugiego klucza interfejsu API: klucza certyfikatu wersji. Więcej informacji na temat uzyskiwania 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 upraszcza uzyskanie klucza interfejsu API.
Krok 1. Utwórz projekt Wander na podstawie szablonu map
- Utwórz nowy projekt Android Studio.
- Wybierz szablon Aktywność w Mapach Google.
- Nazwij projekt
Wander
. - Ustaw minimalny poziom API na API 19. Upewnij się, że językiem jest Kotlin.
- Kliknij Zakończ.
- Gdy aplikacja będzie gotowa, zajrzyj do swojego projektu i tych plików związanych z mapami, które Android Studio tworzy dla Ciebie:
google_maps_api.xml – ten plik konfiguracji służy do przechowywania klucza interfejsu API. Szablon generuje dwa pliki google_maps_api.xml – jeden na potrzeby debugowania i jeden na potrzeby wersji. Plik klucza interfejsu API certyfikatu debugowania znajduje się w katalogu src/debug/res/values. Plik klucza interfejsu API certyfikatu wersji znajduje się w katalogu src/release/res/values. W tym ćwiczeniu z programowania korzystasz tylko z certyfikatu debugowania.
activity_maps.xml – plik układu zawiera jeden fragment, który wypełnia cały ekran. Klasa SupportMapFragment
jest podklasą klasy Fragment
. SupportMapFragment
to najprostsza metoda umieszczania mapy w aplikacji. Otoka kodu wokół widoku mapy, która automatycznie spełnia niezbędne potrzeby w cyklu życia.
Możesz uwzględnić atrybut 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
()
), aby automatycznie inicjować system map i widok. Aktywność zawierająca SupportMapFragment
musi implementować interfejs OnMapReadyCallback
oraz metodę onMapReady()
tego interfejsu. Metoda onMapReady()
jest wywoływana podczas ładowania mapy.
Krok 2. Uzyskaj klucz interfejsu API
- Otwórz wersję debugowania pliku google_maps_api.xml.
- W pliku znajdź komentarz z długim adresem URL. Parametry adresu URL zawierają konkretne informacje o aplikacji.
- Skopiuj adres URL i wklej go w przeglądarce.
- Postępuj zgodnie z wyświetlanymi instrukcjami, by utworzyć projekt na stronie Interfejsy API i usługi. Ze względu na parametry podane w adresie URL strona wie, że ma automatycznie włączyć pakiet Maps SDK na Androida.
- Kliknij Create API API (Utwórz klucz interfejsu API).
- Na następnej stronie przejdź do sekcji Klucze API i kliknij utworzony przed chwilą klucz.
- Kliknij Ogranicz klucz i wybierz Mapy SDK na Androida, by 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ągugoogle_maps_key
w miejscuYOUR_KEY_HERE
. - Uruchom aplikację. W swojej aktywności powinna pojawić się 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 Kotlinie, zmień nazwę z mMap
na map
.
- W aplikacji
MapsActivity
kliknij prawym przyciskiem myszymMap
i wybierz Refaktor i Zmień nazwę...
- Zmień nazwę zmiennej na
map
.
Zwróć uwagę, że wszystkie odwołania do mMap
w funkcji onMapReady()
zmieniają się również na map
.
Mapy Google udostępniają kilka typów mapy: normalne, hybrydowe, satelitarne, terenowe oraz "none" (w ogóle nie są dostępne).
Normalna mapa | Mapa satelitarna | Mapa hybrydowa | Mapa terenu |
Każdy typ mapy dostarcza innych rodzajów informacji. Na przykład podczas korzystania z nawigacji w Mapach Google warto wyświetlić nazwy ulic, aby skorzystać z opcji normalnej. Mapa ukształtowania terenu może ułatwić Ci określenie, ile jeszcze szczytów dotrzeć, aby dotrzeć na szczyt.
W tym zadaniu:
- Dodawanie paska aplikacji z menu opcji, który umożliwia zmianę typu mapy
- Przesuń lokalizację początkową na mapie do swojej lokalizacji domowej.
- Dodaj obsługę znaczników, które wskazują pojedyncze lokalizacje na mapie i mogą obejmować etykiety.
Dodaj menu typów map
W tym kroku dodasz pasek aplikacji z menu opcji, które pozwolą użytkownikowi zmienić typ mapy.
- Aby utworzyć nowy plik XML menu, kliknij prawym przyciskiem myszy katalog res i wybierz Nowy plik zasobów Androida.
- W oknie dialogowym nadaj plikowi nazwę
map_options
. - Jako typ zasobu wybierz Menu.
- Kliknij OK.
- Zastąp kod w nowym pliku na karcie Kod tym kodem, aby utworzyć opcje menu mapy. Typ „"none"” jest pomijany, ponieważ "none" powoduje brak mapy. Ten krok powoduje błąd, ale można go rozwiązać w następnym.
<?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
strings.xml
dodaj zasoby dla atrybutówtitle
, aby naprawić 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 zawyż menu w pliku zasobówmap_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ły typu mapy, by 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ę na to, 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 utworzono Mapy Google. Domyślne wywołanie zwrotne będzie też animować mapę, by przesunąć ją do Sydney.
W tym zadaniu kamera przesuwa mapę do Twojego domu, zbliża się do określonego poziomu i umieszcza w nim znacznik.
Krok 1. Powiększ widok domu i dodaj znacznik
- W pliku
MapsActivity.kt
znajdź metodęonMapReady()
. Usuń znajdujący się w nim kod, który powoduje umieszczenie znacznika w Sydney i przesuwa kamerę. Tak powinna teraz wyglądać Twoja metoda.
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
}
- Aby uzyskać szerokość i długość geograficzną domu, wykonaj te instrukcje.
- Utwórz wartość szerokości i długości geograficznej, a następnie podaj wartości zmiennoprzecinkowe.
val latitude = 37.422160
val longitude = -122.084270
- Utwórz nowy obiekt
LatLng
o nazwiehomeLatLng
. W obiekciehomeLatLng
przekaż nowo utworzone wartości.
val homeLatLng = LatLng(latitude, longitude)
- Utwórz model
val
określający, jak chcesz powiększyć mapę. Użyj poziomu powiększenia 15f.
val zoomLevel = 15f
Poziom powiększenia steruje powiększeniem mapy. Na poniższej liście znajdziesz informacje o poziomie szczegółowości na poszczególnych poziomach powiększenia:
1
: świat5
: ląd/kontynent10
: miasto15
: ulice20
: budynki
- Przenieś aparat do kamery
homeLatLng
, wywołując funkcjęmoveCamera()
w obiekciemap
i przekazując obiektCameraUpdate
przy użyciuCameraUpdateFactory.newLatLngZoom()
. Przekaż obiekthomeLatLng
izoomLevel
.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
- Dodaj znacznik do mapy na
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 swoją aplikację. Mapa powinna przesunąć się po domu, powiększyć odpowiedni poziom i umieścić znacznik w domu.
Krok 2. Zezwól użytkownikom na dodawanie znacznika długim kliknięciem
W tym kroku dodajesz znacznik, gdy użytkownik dotknie lokalizacji na mapie i ją przytrzyma.
- Utwórz zaktualizowaną metodę w
MapsActivity
o nazwiesetMapLongClick()
, która przyjmujeGoogleMap
jako argument. - Podłącz detektor
setOnMapLongClickListener
do obiektu mapy.
private fun setMapLongClick(map:GoogleMap) {
map.setOnMapLongClickListener { }
}
- W
setOnMapLongClickListener()
wywołaj metodęaddMarker()
. Nowy obiektMarkerOptions
z ustawioną pozycjąLatLng
.
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
map.addMarker(
MarkerOptions()
.position(latLng)
)
}
}
- Na końcu metody
onMapReady()
wywołajsetMapLongClick()
za pomocą wywołaniamap
.
override fun onMapReady(googleMap: GoogleMap) {
...
setMapLongClick(map)
}
- Uruchom aplikację.
- Naciśnij i przytrzymaj mapę, aby umieścić znacznik w wybranej lokalizacji.
- Kliknij znacznik, aby wyśrodkować go na ekranie.
Krok 3. Dodaj okno informacyjne dla znacznika
W tym kroku dodasz kolumnę InfoWindow
, w której wyświetlane są współrzędne znacznika po kliknięciu.
- W
setMapLongClick()setOnMapLongClickListener()
utwórzval
dla użytkownikasnippet
. Fragment to dodatkowy tekst wyświetlany po tytule. Fragment kodu zawiera 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 polu
addMarker()
ustawtitle
znacznika znacznika „Pinezka”, korzystając z zasobu ciąguR.string.
dropped_pin
. - Ustaw znacznik
snippet
nasnippet
.
Ukończona 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ę.
- Naciśnij i przytrzymaj mapę, by upuścić znacznik lokalizacji.
- Kliknij znacznik, aby wyświetlić okno informacyjne.
Krok 4. Dodaj detektor ważnych miejsc
Domyślnie na mapie wyświetlane są ciekawe miejsca wraz z odpowiednimi ikonami. Ciekawe miejsca obejmują parki, szkoły, budynki administracji publicznej oraz inne obiekty. Po ustawieniu typu mapy na normal
zobaczysz na niej ciekawe miejsca. Ciekawe miejsca reprezentują firmy, takie jak sklepy, restauracje czy hotele.
W tym kroku dodasz do mapy obiekt GoogleMap.OnPoiClickListener
. Detektor kliknięć wstawia znacznik na mapie natychmiast po kliknięciu ważnego miejsca. Detektor kliknięć wyświetla też okno informacyjne z nazwą ciekawego miejsca.
- Utwórz zaktualizowaną metodę w
MapsActivity
o nazwiesetPoiClick()
, która przyjmujeGoogleMap
jako argument. - W metodzie
setPoiClick()
ustawOnPoiClickListener
w przekazywanymGoogleMap
.
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
}
}
- W
setOnPoiClickListener()
utwórzval poiMarker
dla znacznika . - Ustaw na nim znacznik za pomocą
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()
poiMarker
, by od razu wyświetlić okno informacyjne.
poiMarker.showInfoWindow()
Końcowy 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()
}
}
- Pod koniec
onMapReady()
zadzwoń do:setPoiClick()
i przekaż w ciągumap
.
override fun onMapReady(googleMap: GoogleMap) {
...
setPoiClick(map)
}
- Uruchom aplikację i znajdź ciekawe miejsce, np. park lub kawiarnię.
- Kliknij ważne miejsce, aby umieścić na nim znacznik, a w oknie informacyjnym wyświetlić jego nazwę.
Mapy Google możesz dostosować na wiele sposobów, aby nadać swojej mapie niepowtarzalny wygląd.
Obiekt MapFragment
możesz dostosować za pomocą dostępnych atrybutów XML, tak jak w przypadku każdego innego fragmentu. Na tym etapie dostosujesz wygląd i sposób działania treści elementu MapFragment
, korzystając z metod znajdujących się na obiekcie GoogleMap
.
Aby utworzyć własny styl mapy, generujesz plik JSON określający sposób wyświetlania obiektów na mapie. Nie musisz ręcznie tworzyć tego pliku JSON. Google udostępnia kreator stylu Map Google, który generuje kod JSON po zmianie wyglądu mapy. W tym zadaniu stylizujesz mapę w stylu retro, co oznacza, że mapa wykorzystuje stare kolory i dodajesz kolorowe drogi.
Krok 1: Utwórz styl mapy
- W przeglądarce otwórz stronę https://mapstyle.withgoogle.com/.
- Wybierz Utwórz styl.
- Wybierz Retro.
- Kliknij Więcej opcji.
- Z listy Typ funkcji wybierz Droga & Wypełnienie.
- Zmień kolor dróg na dowolny wybrany (np. różowy).
- Kliknij Zakończ.
- Skopiuj kod JSON z wyświetlonego okna i opcjonalnie zapisz go w postaci zwykłego tekstu do użycia 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
. używasz zasobów kataloguraw
, takich jak kod JSON; - Utwórz plik (
res/raw
) o nazwiemap_style.json
. - Wklej otrzymany kod JSON do nowego pliku zasobów.
- W narzędziu
MapsActivity
utwórz zmienną klasyTAG
nad metodąonCreate()
. Te dane służą do logowania.
private val TAG = MapsActivity::class.java.simpleName
- W narzędziu
MapsActivity
utwórz też funkcjęsetMapStyle()
, która przyjmuje właściwośćGoogleMap
. - W
setMapStyle()
dodaj bloktry{}
. - W bloku
try{}
utwórzval success
dla sukcesu. Dodajesz ten blok. - W bloku
try{}
ustaw styl JSON na mapę, wywołajsetMapStyle()
przy obiekcieGoogleMap
. przekazać obiektMapStyleOptions
, który wczytuje plik JSON; - Przypisz wynik do gestu
success
. MetodasetMapStyle()
zwraca wartość logiczną oznaczającą stan analizy pliku stylu i określenia 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ę if (fałsz) dla
success
. Jeśli styl nie powiedzie się, 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 rozwiązać problem z brakującym plikiem stylu. Jeśli w blokucatch
nie można wczytać pliku, wywołajResources.NotFoundException
.
private fun setMapStyle(map: GoogleMap) {
try {
...
} catch (e: Resources.NotFoundException) {
Log.e(TAG, "Can't find style. Error: ", e)
}
}
Ukończona 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ą obiektGoogleMap
.
override fun onMapReady(googleMap: GoogleMap) {
...
setMapStyle(map)
}
- Uruchom aplikację.
- Ustaw tryb mapy na
normal
, a nowy styl powinien być widoczny w stylu retro i przez wybrane przez Ciebie drogi.
Krok 3. Dostosuj styl znacznika
Mapę możesz spersonalizować, stosując styl znaczników mapy. W tym kroku zmieniasz domyślne czerwone znaczniki na bardziej charakterystyczne.
- W metodzie
onMapLongClick()
dodaj poniższy wiersz kodu do elementuMarkerOptions()
konstruktora, aby użyć znacznika domyślnego, ale zmień 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ę. Znaczniki, które pojawią się po długim kliknięciu, będą teraz cieniowane na niebiesko. Znaczniki użytecznych miejsc są nadal czerwone, ponieważ styl nie został dodany do metody
onPoiClick()
.
Jednym ze sposobów dostosowywania mapy Google jest rysowanie na niej. Ta technika jest przydatna, gdy chcesz wyróżnić określony typ lokalizacji, na przykład popularne łowiska.
- Kształty: możesz dodawać do mapy linie, wielokąty i okręgi.
- Obiekty
GroundOverlay
: nakładka gruntowa to obraz ustalony na mapie. W przeciwieństwie do znaczników nakładki na powierzchni są kierowane na powierzchnię Ziemi, a nie na ekran. Obracanie, pochylanie lub powiększanie mapy zmienia orientację zdjęcia. Nakładki na powierzchni są przydatne, gdy chcesz poprawić jeden obraz na jednym obszarze na mapie.
Krok: dodaj warstwę naziemną
W tym zadaniu dodasz nakładkę domową w postaci kształtu Androida do swojej lokalizacji domowej.
- Pobierz ten obraz Androida i zapisz go w folderze
res/drawable
. Sprawdź, czy nazwa pliku toandroid.png
.
- Po wywołaniu funkcji
onMapReady()
przenieś kamerę w pozycję 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 graficznego. - Przekaż otrzymany obiekt
BitmapDescriptor
do metodyimage()
obiektuGroundOverlayOptions
.
val androidOverlay = GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.android))
- Utwórz wartość
float overlaySize
dla szerokości wybranej nakładki. W tym przykładzie sprawdza się szerokość100f
.
Ustaw właściwość position
obiektu GroundOverlayOptions
, wywołując metodę position()
, a następnie przekaż obiekt homeLatLng
i overlaySize
.
val overlaySize = 100f
val androidOverlay = GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.android))
.position(homeLatLng, overlaySize)
- Wywołaj
addGroundOverlay()
obiektuGoogleMap
i przekaż go w obiekcieGroundOverlayOptions
.
map.addGroundOverlay(androidOverlay)
- Uruchom aplikację.
- Zmień wartość
zoomLevel
na 18f, aby zobaczyć obraz Androida jako nakładkę.
Użytkownicy często używają Map Google do sprawdzania swojej bieżącej lokalizacji. Aby wyświetlić lokalizację urządzenia na mapie, możesz użyć warstwy danych-lokalizacji.
Warstwa danych o lokalizacji dodaje do mapy opcję Moja lokalizacja. Gdy użytkownik naciśnie przycisk, mapa zostanie wyśrodkowana na urządzeniu. Lokalizacja jest widoczna jako niebieska kropka, jeśli urządzenie jest nieruchome, lub jako niebieski szewron, gdy urządzenie się porusza.
W tym zadaniu włączysz warstwę danych-lokalizacji.
Krok: poproś o dostęp do lokalizacji
Włączenie śledzenia lokalizacji w Mapach Google wymaga pojedynczego wiersza kodu. Musisz się jednak upewnić, że użytkownik przyznał dostęp do lokalizacji (korzystając z modelu uprawnień czasu działania).
W tym kroku poprosisz o dostęp do lokalizacji i włączysz śledzenie lokalizacji.
- W pliku
AndroidManifest.xml
sprawdź, czy uprawnieniaFINE_LOCATION
już są obecne. Android Studio wstawił te uprawnienia, gdy wybierałeś szablon Map Google.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- W
MapsActivity
utwórz zmienną typuREQUEST_LOCATION_PERMISSION
.
private val REQUEST_LOCATION_PERMISSION = 1
- Aby sprawdzić, czy uprawnienia zostały przyznane, utwórz w
MapsActivity
metodę o nazwieisPermissionGranted()
. W ramach tej metody sprawdź, czy użytkownik przyznał odpowiednie 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 podaje żadnych argumentów i nie zwraca niczego. Sprawdź, czy masz uprawnienieACCESS_FINE_LOCATION
. Jeśli tak, włącz warstwę lokalizacji. W przeciwnym razie poproś o zgodę.
private fun enableMyLocation() {
if (isPermissionGranted()) {
map.isMyLocationEnabled = true
}
else {
ActivityCompat.requestPermissions(
this,
arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION_PERMISSION
)
}
}
- Wywołaj
enableMyLocation()
z wywołaniem zwrotnymonMapReady()
, aby włączyć warstwę lokalizacji.
override fun onMapReady(googleMap: GoogleMap) {
...
enableMyLocation()
}
- Zastąp metodę
onRequestPermissionsResult()
. Jeśli uprawnienierequestCode
jest równeREQUEST_LOCATION_PERMISSION
, a tablicagrantResults
nie jest pusta zPackageManager.PERMISSION_GRANTED
w pierwszym boksie, 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. Zezwól na to.
Na mapie wyświetla się bieżąca lokalizacja urządzenia za pomocą niebieskiej kropki. Zwróć uwagę na przycisk lokalizacji. Jeśli przesuniesz mapę i klikniesz ten przycisk, wyśrodkujesz mapę z powrotem na urządzeniu.
Pobierz kod ukończonych ćwiczeń z programowania.
$ 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 API Map Google, potrzebujesz klucza interfejsu API z Konsoli interfejsów API Google.
- W Androidzie Studio użycie szablonu aktywności w Mapach Google powoduje wygenerowanie
Activity
z pojedynczymSupportMapFragment
w układzie aplikacji. Szablon dodaje również plikACCESS_FINE_PERMISSION
do pliku manifestu aplikacji i implementujeOnMapReadyCallback
w aktywności, zastępując wymaganą metodęonMapReady()
.
Aby zmienić typ mapy GoogleMap
w czasie działania, użyj metody GoogleMap.setMapType()
. Mapą Google może być jeden z tych typów map:
- Normalny: typowa mapa drogi. Pokazuje drogi, niektóre obiekty utworzone przez ludzi, a także ważne obiekty przyrodnicze, takie jak rzeki. Widoczne są również etykiety dróg i obiektów.
- Hybrydowa: dane zdjęć satelitarnych z dodanymi mapami drogowymi. Widoczne są również etykiety dróg i obiektów.
- Satelita: dane zdjęcia. Etykiety dróg i obiektów nie są widoczne.
- Teren: dane topograficzne. Na mapie znajdują się kolory, linie konturów i etykiety oraz cieniowanie perspektywy. Widoczne są również niektóre drogi i etykiety.
- Brak: brak podstawowych kafelków mapy.
Informacje o Mapach Google:
- Znacznik jest wskaźnikiem określonej lokalizacji geograficznej.
- Po dotknięciu domyślny znacznik wyświetla okno informacyjne z informacjami o lokalizacji.
- Domyślnie na mapie podstawowej wyświetlane są ciekawe miejsca wraz z odpowiednimi ikonami. Ciekawe miejsca obejmują parki, szkoły, budynki administracji publicznej oraz inne obiekty.
- Dodatkowo zdjęcia ważnych miejsc (sklepy, restauracje, hotele i inne) domyślnie wyświetlają się na mapie, gdy typ mapy to
normal
. - Za pomocą
OnPoiClickListener
możesz przechwytywać kliknięcia ważnych miejsc. - Używając kreatora stylu, możesz zmienić wygląd prawie wszystkich elementów mapy Google. Kreator stylu wygeneruje plik JSON, który przekażesz do Map Google za pomocą metody
setMapStyle()
. - Możesz dostosować znaczniki, zmieniając kolor domyślny lub zastępując domyślną ikonę znacznika własnym obrazem.
Inne ważne informacje:
- Aby dopasować obraz do położenia geograficznego, użyj nakładki na powierzchni.
- Użyj obiektu
GroundOverlayOptions
, aby określić obraz, jego rozmiar w metrach i pozycję jego obrazu. Przekaż ten obiekt do metodyGoogleMap.addGroundOverlay()
, aby ustawić nakładkę na mapie. - Jeśli Twoja aplikacja ma uprawnienia
ACCESS_FINE_LOCATION
, możesz włączyć śledzenie lokalizacji, ustawiającmap.isMyLocationEnabled = true
. - Nie obejmuje on tych ćwiczeń z programowania, ale możesz podać dodatkowe informacje o danej lokalizacji, korzystając z Google Street View – zdjęcia panoramicznego danego miejsca, po którym można się poruszać.
Dokumentacja dla programistów Androida:
- Rozpocznij
- Dodawanie mapy za pomocą znacznika
- Obiekty na mapie
- Dodawanie mapy stylu
- Street View
- Nakładki na powierzchni
Dokumentacja referencyjna:
Linki do innych ćwiczeń z programowania w tym kursie znajdziesz na stronie Zaawansowane ćwiczenia z Androida w Kotlin.