Funzionalità Android avanzate in Kotlin 04.1: Google Maps per Android

1. Prima di iniziare

La creazione di app con Google Maps ti consente di aggiungere funzioni alla tua app, quali immagini satellitari, controlli dell'interfaccia utente affidabili per le mappe, monitoraggio della posizione e indicatori di posizione. Puoi aggiungere valore alle mappe standard di Google Maps mostrando informazioni ricavate dal tuo set di dati, ad esempio le località di note aree di pesca o di arrampicata. Puoi anche creare giochi in cui il giocatore esplora il mondo fisico, ad esempio con una caccia al tesoro o persino con giochi di realtà aumentata.

In questa lezione creerai un'app di Google Maps chiamata Wander, che mostra mappe personalizzate e la posizione dell'utente.

Prerequisiti

Conoscenza di quanto segue:

  • Come creare un'app per Android di base ed eseguirla con Android Studio.
  • Creare e gestire risorse, ad esempio le stringhe.
  • Come eseguire il refactoring del codice e rinominare le variabili con Android Studio
  • Come utilizzare una mappa di Google come utente.
  • Come impostare le autorizzazioni di runtime.

Obiettivi didattici

  • Come ottenere una chiave API dalla console API di Google e registrare la chiave nella tua app
  • Come integrare una mappa Google nell'app
  • Come visualizzare diversi tipi di mappe
  • Come definire uno stile per la mappa di Google
  • Come aggiungere indicatori alla mappa
  • Come consentire all'utente di posizionare un indicatore su un punto d'interesse (PDI)
  • Come attivare il monitoraggio della posizione
  • Come creare l'app Wander, che ha una mappa Google incorporata
  • Come creare funzionalità personalizzate per la tua app, ad esempio indicatori e stile
  • Come attivare il monitoraggio della posizione nell'app

2. Panoramica app

In questo codelab, creerai l'app Wander, che mostra una mappa Google con stili personalizzati. L'app Wander ti consente di inserire indicatori su luoghi, aggiungere overlay e visualizzare la tua posizione in tempo reale.

5b12eda7f467bc2f.png

3. Attività: configura il progetto e ottieni una chiave API

Maps SDK for Android richiede una chiave API. Per ottenere la chiave API, registra il tuo progetto nel riquadro API & pagina Servizi. La chiave API è collegata a un certificato digitale che collega l'app al suo autore. Per ulteriori informazioni sull'utilizzo dei certificati digitali e sulla firma dell'app, vedi Firmare l'app.

In questo codelab, utilizzerai la chiave API per il certificato di debug. Il certificato di debug non è sicuro, come descritto in Firmare la build di debug. Le app per Android pubblicate che utilizzano Maps SDK for Android richiedono una seconda chiave API: la chiave per il certificato di rilascio. Per ulteriori informazioni su come ottenere un certificato di rilascio, consulta l'argomento Ottenere una chiave API.

Android Studio include un modello di attività su Google Maps, che genera un codice modello utile. Il codice del modello include un file google_maps_api.xml contenente un link che semplifica l'ottenimento di una chiave API.

Passaggio 1: crea il progetto Wander con il modello di mappe

  1. Crea un nuovo progetto Android Studio.
  2. Seleziona il modello Attività su Google Maps.

d6b874bb19ea68cd.png

  1. Assegna al progetto il nome Wander.
  2. Imposta il livello API minimo su API 19. Assicurati che la lingua sia Kotlin.
  3. Fai clic su Fine.
  4. Una volta completata la creazione dell'app, dai un'occhiata al tuo progetto e ai seguenti file relativi alle mappe creati da Android Studio per te:

google_maps_api.xml: utilizza questo file di configurazione per contenere la chiave API. Il modello genera due file google_maps_api.xml: uno per il debug e uno per il rilascio. Il file della chiave API per il certificato di debug si trova in src/debug/res/values. Il file della chiave API per il certificato di rilascio si trova in src/release/res/values. In questo codelab, utilizzerai solo il certificato di debug.

activity_maps.xml: questo file di layout contiene un singolo frammento che riempie l'intero schermo. La classe SupportMapFragment è una sottoclasse della classe Fragment. Un SupportMapFragment è il modo più semplice per inserire una mappa in un'app. È un wrapper intorno alla vista di una mappa per gestire automaticamente le esigenze necessarie del ciclo di vita.

Puoi includere SupportMapFragment in un file di layout utilizzando un tag <fragment> in qualsiasi ViewGroup, con un ulteriore attributo name.

android:name="com.google.android.gms.maps.SupportMapFragment"

MapsActivity.java: il file MapsActivity.java crea un'istanza del SupportMapFragment nel metodo onCreate() e utilizza la classe getMapAsync() per inizializzare automaticamente il sistema delle mappe e la vista. L'attività che contiene SupportMapFragment deve implementare l'interfaccia OnMapReadyCallback e il metodo onMapReady() dell'interfaccia. Il metodo onMapReady() viene chiamato quando la mappa viene caricata.

Passaggio 2: ottieni la chiave API

  1. Apri la versione di debug del file google_maps_api.xml.
  2. Cerca nel file un commento con un URL lungo. I parametri dell'URL includono informazioni specifiche sulla tua app.
  3. Copia e incolla l'URL in un browser.
  4. Segui le istruzioni per creare un progetto nella piattaforma API e pagina Servizi. A causa dei parametri nell'URL fornito, la pagina sa che deve attivare automaticamente Maps SDK for Android.
  5. Fai clic su Create an API Key (Crea una chiave API).
  6. Nella pagina successiva, vai alla sezione Chiavi API e fai clic sulla chiave appena creata.
  7. Fai clic su Limita chiave e seleziona Maps SDK for Android per limitare l'utilizzo della chiave alle app Android.
  8. Copia la chiave API generata. Inizia con "AIza".
  9. Nel file google_maps_api.xml, incolla la chiave nella stringa google_maps_key nel punto YOUR_KEY_HERE.
  10. Esegui l'app. Dovresti vedere una mappa incorporata nella tua attività con un indicatore impostato a Sydney, in Australia. L'indicatore di Sydney fa parte del modello e lo modifichi in seguito.

34dc9dd877c90996.png

Passaggio 3: rinomina mMap

MapsActivity ha un var privato lateinit denominato mMap, che è di tipo GoogleMap. Per seguire le convenzioni di denominazione di Kotlin, cambia il nome di mMap in map.

  1. In MapsActivity, fai clic con il tasto destro del mouse su mMap e fai clic su Refactoring > Rinomina...

e713ccb3384450c6.png

  1. Cambia il nome della variabile in map.

Nota come anche tutti i riferimenti a mMap nella funzione onMapReady() cambiano in map.

4. Attività: aggiungi tipi di mappe

Google Maps include diversi tipi di mappe: normale, ibrida, satellitare, rilievo e "nessuno" (per nessuna mappa).

Mappa normale

Mappa satellitare

Mappa ibrida

Mappa del terreno

Ogni tipo di mappa fornisce tipi diversi di informazioni. Ad esempio, quando utilizzi le mappe per la navigazione in auto, è utile vedere i nomi delle vie, in modo da poter utilizzare l'opzione normale. Quando fai un'escursione, la mappa del terreno può essere utile per decidere quanto ancora salire per arrivare in cima.

In questa attività:

  1. Aggiungi una barra delle app con un menu opzioni che consente all'utente di modificare il tipo di mappa.
  2. Sposta la posizione iniziale della mappa nella tua posizione di casa.
  3. Aggiungi un supporto per gli indicatori, che indicano singole posizioni su una mappa e possono includere un'etichetta.

Aggiungi un menu per i tipi di mappa

In questo passaggio, aggiungi una barra dell'app con un menu opzioni che consente all'utente di modificare il tipo di mappa.

  1. Per creare un nuovo file XML del menu, fai clic con il tasto destro del mouse sulla directory res e seleziona New > File di risorse Android.
  2. Nella finestra di dialogo, assegna al file il nome map_options.
  3. Scegli Menu per il tipo di risorsa.
  4. Fai clic su OK.
  5. Nella scheda Codice, sostituisci il codice nel nuovo file con il codice riportato di seguito per creare le opzioni del menu della mappa. "Nessuno" tipo di mappa omesso perché "nessuno" comporta l'assenza di alcuna mappa. Questo passaggio causa un errore, ma lo risolvi nel passaggio successivo.
<?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>
  1. In strings.xml, aggiungi risorse per gli attributi title in modo da risolvere gli errori.
<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>
  1. In MapsActivity, esegui l'override del metodo onCreateOptionsMenu() e gonfia il menu dal file di risorse map_options.
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
   val inflater = menuInflater
   inflater.inflate(R.menu.map_options, menu)
   return true
}
  1. In MapsActivity.kt, sostituisci il metodo onOptionsItemSelected(). Modifica il tipo di mappa utilizzando le costanti di tipo mappa in modo che riflettano la selezione dell'utente.
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)
}
  1. Esegui l'app.
  2. Fai clic su 428da163b831115b.png per modificare il tipo di mappa. Osserva come l'aspetto della mappa cambia tra le diverse modalità.

6fa42970d87f5dc7.png

5. Attività: aggiungi indicatori

Per impostazione predefinita, il callback onMapReady() include il codice che posiziona un indicatore a Sydney, in Australia, dove è stato creato Google Maps. Il callback predefinito anima anche la mappa per eseguire la panoramica verso Sydney.

In questa attività, farai spostare la fotocamera della mappa verso casa tua, esegui lo zoom su un livello da te specificato e collochi lì un indicatore.

Passaggio 1: esegui lo zoom sulla tua casa e aggiungi un indicatore

  1. Nel file MapsActivity.kt, trova il metodo onMapReady(). Rimuovi il codice che posiziona l'indicatore a Sydney e sposta la videocamera. Questo è l'aspetto attuale del tuo metodo.
override fun onMapReady(googleMap: GoogleMap) {
   map = googleMap

}
  1. Per trovare la latitudine e la longitudine di casa tua, segui queste istruzioni.
  2. Crea un valore per la latitudine e un valore per la longitudine e inserisci i relativi valori in virgola mobile.
val latitude = 37.422160
val longitude = -122.084270
  1. Crea un nuovo oggetto LatLng denominato homeLatLng. Nell'oggetto homeLatLng, passa i valori appena creati.
val homeLatLng = LatLng(latitude, longitude)
  1. Crea un val per lo zoom che vuoi sulla mappa. Utilizza il livello di zoom 15f.
val zoomLevel = 15f

Il livello di zoom controlla l'aumento dello zoom sulla mappa. L'elenco che segue ti dà un'idea del livello di dettaglio mostrato da ogni livello di zoom:

  • 1: mondo
  • 5: massa continentale/continente
  • 10: città
  • 15: strade
  • 20: edifici
  1. Sposta la videocamera in homeLatLng chiamando la funzione moveCamera() sull'oggetto map e passala in un oggetto CameraUpdate utilizzando CameraUpdateFactory.newLatLngZoom(). Passa l'oggetto homeLatLng e l'zoomLevel.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
  1. Aggiungi un indicatore alla mappa in homeLatLng.
map.addMarker(MarkerOptions().position(homeLatLng))

Il metodo finale dovrebbe essere simile al seguente:

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))
}
  1. Esegui l'app. La mappa dovrebbe eseguire una panoramica fino alla tua casa, aumentare lo zoom fino al livello desiderato e posizionare un indicatore sulla tua casa.

fc939024778ee76.png

Passaggio 2: consenti agli utenti di aggiungere un indicatore con un clic lungo

In questo passaggio, devi aggiungere un indicatore quando l'utente tocca e tiene premuto un luogo sulla mappa.

  1. Creare in MapsActivity uno stub del metodo denominato setMapLongClick() che utilizza GoogleMap come argomento.
  2. Collega un listener setOnMapLongClickListener all'oggetto mappa.
private fun setMapLongClick(map:GoogleMap) {
   map.setOnMapLongClickListener { }
}
  1. In setOnMapLongClickListener(), chiama il metodo addMarker(). Trasmetti un nuovo oggetto MarkerOptions con la posizione impostata su LatLng trasmesso.
private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       map.addMarker(
           MarkerOptions()
               .position(latLng)
       )
   }
}
  1. Al termine del metodo onMapReady(), chiama setMapLongClick() con map.
override fun onMapReady(googleMap: GoogleMap) {
   ...
  
   setMapLongClick(map)
}
  1. Esegui l'app.
  2. Tocca e tieni premuto sulla mappa per posizionare un indicatore in un luogo.
  3. Tocca l'indicatore in modo che venga centrato sullo schermo.

4ff8d1c1db3bca9e.png

Passaggio 3: aggiungi una finestra informativa per l'indicatore

In questo passaggio, aggiungi un InfoWindow che mostra le coordinate dell'indicatore quando quest'ultimo viene toccato.

  1. In setMapLongClick()setOnMapLongClickListener(), crea un val per snippet. Uno snippet è testo aggiuntivo che viene visualizzato dopo il titolo. Lo snippet mostra la latitudine e la longitudine di un indicatore.
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)
       )
   }
}
  1. In addMarker(), imposta title dell'indicatore su Segnaposto inserito utilizzando una risorsa stringa R.string.dropped_pin.
  2. Imposta snippet dell'indicatore su snippet.

La funzione completata ha il seguente aspetto:

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)
              
       )
   }
}
  1. Esegui l'app.
  2. Tocca e tieni premuta la mappa per inserire un indicatore di posizione.
  3. Tocca l'indicatore per mostrare la finestra informativa.

63f210e6e47dfa29.png

Passaggio 4: aggiungi un listener di PDI

Per impostazione predefinita, i punti d'interesse (PDI) vengono visualizzati sulla mappa insieme alle icone corrispondenti. I PDI includono parchi, scuole, edifici governativi e altro ancora. Se il tipo di mappa è impostato su normal, i PDI delle attività vengono visualizzati anche sulla mappa. I PDI di un'attività rappresentano attività commerciali, ad esempio negozi, ristoranti e hotel.

In questo passaggio, aggiungi una GoogleMap.OnPoiClickListener alla mappa. Questo listener di clic posiziona un indicatore sulla mappa immediatamente quando l'utente fa clic su un PDI. Il listener di clic visualizza anche una finestra informativa contenente il nome del PDI.

  1. Creare in MapsActivity uno stub del metodo denominato setPoiClick() che utilizza GoogleMap come argomento.
  2. Nel metodo setPoiClick(), imposta un OnPoiClickListener per il valore GoogleMap trasmesso.
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->

   }
}
  1. Nell'setOnPoiClickListener(), crea un val poiMarker per l'indicatore .
  2. Impostalo come indicatore utilizzando map.addMarker() e MarkerOptions impostando title sul nome del PDI.
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
   }
}
  1. Nella funzione setOnPoiClickListener(), chiama showInfoWindow() su poiMarker per visualizzare immediatamente la finestra informativa.
poiMarker.showInfoWindow()

Il codice finale per la funzione setPoiClick() dovrebbe essere simile al seguente.

private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
       poiMarker.showInfoWindow()
   }
}
  1. Alla fine del onMapReady(), chiama setPoiClick() e passa tra map.
override fun onMapReady(googleMap: GoogleMap) {
   ...

   setPoiClick(map)
}
  1. Esegui l'app e trova un PDI, ad esempio un parco o un bar.
  2. Tocca il PDI per posizionare un indicatore e visualizzarne il nome in una finestra informativa.

f4b0972c75d5fa5f.png

6. Attività: personalizza lo stile della mappa

Puoi personalizzare Google Maps in molti modi, dando alla tua mappa un aspetto unico.

Puoi personalizzare un oggetto MapFragment utilizzando gli attributi XML disponibili, come faresti con qualsiasi altro frammento. Tuttavia, in questo passaggio personalizzerai l'aspetto dei contenuti dell'elemento MapFragment, utilizzando i metodi sull'oggetto GoogleMap.

Per creare uno stile personalizzato per la mappa, devi generare un file JSON che specifica come vengono visualizzati gli elementi nella mappa. Non è necessario creare manualmente questo file JSON. Google fornisce la procedura guidata degli stili di Maps Platform, che genera automaticamente il codice JSON dopo aver definito visivamente lo stile della mappa. In questa attività, definisci lo stile della mappa con un tema retrò, nel senso che la mappa utilizza colori vintage e aggiungi strade colorate.

Passaggio 1. Crea uno stile per la mappa

  1. Vai all'indirizzo https://mapstyle.withgoogle.com/ nel browser.
  2. Seleziona Crea uno stile.
  3. Seleziona Retrò.

208b3d3aeab0d9b6.png

  1. Fai clic su Altre opzioni.

4a35faaf9535ee82.png

  1. Seleziona Strada > Riempi.
  2. Cambia il colore delle strade con il colore che preferisci (ad es. rosa).

92c3293749293a4c.png

  1. Fai clic su Fine.

f1bfe8585eb69480.png

  1. Copia il codice JSON dalla finestra di dialogo risultante e, se vuoi, conservalo in una nota di testo normale per utilizzarlo nel passaggio successivo.

3c32168b299d6420.png

Passaggio 2: aggiungi lo stile alla mappa

  1. In Android Studio, nella directory res, crea una directory delle risorse e assegnale il nome raw. Utilizzi le risorse della directory raw, come il codice JSON.
  2. Crea un file in res/raw denominato map_style.json.
  3. Incolla il codice JSON accantonato nel nuovo file di risorsa.
  4. In MapsActivity, crea una variabile di classe TAG sopra il metodo onCreate(). Viene utilizzato per scopi di logging.
private val TAG = MapsActivity::class.java.simpleName
  1. Sempre in MapsActivity, crea una funzione setMapStyle() che accetti GoogleMap.
  2. In setMapStyle(), aggiungi un blocco try{}.
  3. Nel blocco try{}, crea una val success per applicare uno stile efficace. Aggiungi il seguente blocco catch.
  4. Nel blocco try{}, imposta lo stile JSON sulla mappa, chiama setMapStyle() sull'oggetto GoogleMap. Passa un oggetto MapStyleOptions, che carica il file JSON.
  5. Assegna il risultato a success. Il metodo setMapStyle() restituisce un valore booleano che indica lo stato di esito positivo dell'analisi del file di stile e dell'impostazione dello stile.
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
           )
       )
   }
}
  1. Aggiungi un'istruzione if per success che è falsa. Se l'applicazione degli stili non riesce, stampa un log di cui l'analisi non è riuscita.
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
       if (!success) {
           Log.e(TAG, "Style parsing failed.")
       }
   }
}
  1. Aggiungi un blocco catch{} per gestire la situazione di un file di stile mancante. Se non è possibile caricare il file nel blocco catch, genera un Resources.NotFoundException.
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
   } catch (e: Resources.NotFoundException) {
       Log.e(TAG, "Can't find style. Error: ", e)
   }
}

Il metodo completato dovrebbe essere simile al seguente snippet di codice:

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)
   }
}
  1. Infine, chiama il metodo setMapStyle() nel metodo onMapReady() che passa nell'oggetto GoogleMap.
override fun onMapReady(googleMap: GoogleMap) {
   ...
   setMapStyle(map)
}
  1. Esegui l'app.
  2. Imposta la mappa sulla modalità normal e il nuovo stile dovrebbe essere visibile con temi retrò e strade del colore scelto.

b59d6cb81f02a14f.png

Passaggio 3. Applica uno stile all'indicatore

Puoi personalizzare ulteriormente la mappa assegnando uno stile agli indicatori. In questo passaggio, modificherai gli indicatori rossi predefiniti in qualcosa di più trendy.

  1. Nel metodo onMapLongClick(), aggiungi la seguente riga di codice a MarkerOptions() del costruttore per utilizzare l'indicatore predefinito, ma cambia il colore in blu.
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))

Ora onMapLongClickListener() ha il seguente aspetto:

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))
   )
}
  1. Esegui l'app. Gli indicatori visualizzati dopo aver fatto clic a lungo sono ora in blu. Tieni presente che gli indicatori dei PDI sono ancora rossi perché non hai aggiunto stili al metodo onPoiClick().

b9916bca3c367e3.png

7. Attività: aggiungi un overlay

Un modo per personalizzare la mappa di Google è disegnarci sopra. Questa tecnica è utile se vuoi mettere in evidenza un particolare tipo di località, come punti di pesca molto conosciuti.

  • Forme: puoi aggiungere polilinee, poligoni e cerchi alla mappa.
  • GroundOverlay oggetti: un overlay al suolo è un'immagine fissata a una mappa. A differenza degli indicatori, le sovrapposizioni del suolo sono orientate alla superficie terrestre anziché allo schermo. La rotazione, l'inclinazione o lo zoom della mappa modifica l'orientamento dell'immagine. Le sovrapposizioni del suolo sono utili quando vuoi correggere una singola immagine in un'area della mappa.

Passaggio: aggiungi un overlay al suolo

In questa attività, aggiungerai un overlay al suolo a forma di Android all'indirizzo di casa tua.

  1. Scarica questa immagine Android e salvala nella cartella res/drawable. Assicurati che il nome del file sia android.png.

61fabd56a0841b44.png

  1. In onMapReady(), al termine della chiamata per spostare la videocamera nella posizione di casa tua, crea un oggetto GroundOverlayOptions.
  2. Assegna l'oggetto a una variabile denominata androidOverlay.
val androidOverlay = GroundOverlayOptions()
  1. Utilizza il metodo BitmapDescriptorFactory.fromResource() per creare un oggetto BitmapDescriptor dalla risorsa immagine scaricata.
  2. Passa l'oggetto BitmapDescriptor risultante nel metodo image() dell'oggetto GroundOverlayOptions.
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
  1. Crea un float overlaySize per la larghezza in metri dell'overlay desiderato. Per questo esempio, la larghezza 100f è ideale.

Imposta la proprietà position per l'oggetto GroundOverlayOptions chiamando il metodo position() e trasmetti l'oggetto homeLatLng e overlaySize.

val overlaySize = 100f
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
   .position(homeLatLng, overlaySize)
  1. Richiama addGroundOverlay() sull'oggetto GoogleMap e passa l'oggetto GroundOverlayOptions.
map.addGroundOverlay(androidOverlay)
  1. Esegui l'app.
  2. Modifica il valore di zoomLevel in 18f per visualizzare l'immagine Android sotto forma di overlay.

b1b25b0acd6a9807.png

8. Attività: attiva il monitoraggio della posizione

Gli utenti spesso usano Google Maps per vedere la loro posizione attuale. Per visualizzare la posizione del dispositivo sulla mappa, puoi utilizzare il livello dati sulla posizione.

Il livello dati sulla posizione aggiunge l'icona La mia posizione alla mappa.

f317f84dcb3ac3a1.png

Quando l'utente tocca il pulsante, la mappa viene centrata sulla posizione del dispositivo. La posizione è indicata da un punto blu se il dispositivo è fermo e da uno chevron blu se il dispositivo è in movimento.

In questa attività, attiverai il livello dei dati sulla posizione.

Passaggio: richiedi le autorizzazioni di accesso alla posizione

L'attivazione del monitoraggio della posizione in Google Maps richiede una singola riga di codice. Tuttavia, devi assicurarti che l'utente abbia concesso le autorizzazioni di accesso alla posizione (utilizzando il modello di autorizzazione di runtime).

In questo passaggio, dovrai richiedere le autorizzazioni di accesso alla posizione e attivare il monitoraggio della posizione.

  1. Nel file AndroidManifest.xml, verifica che l'autorizzazione FINE_LOCATION sia già presente. Android Studio ha inserito questa autorizzazione quando hai selezionato il modello di Google Maps.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  1. In MapsActivity, crea una variabile di classe REQUEST_LOCATION_PERMISSION.
private val REQUEST_LOCATION_PERMISSION = 1
  1. Per verificare se le autorizzazioni sono state concesse, crea un metodo in MapsActivity chiamato isPermissionGranted(). Con questo metodo, verifica se l'utente ha concesso l'autorizzazione.
private fun isPermissionGranted() : Boolean {
  return ContextCompat.checkSelfPermission(
       this,
      Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
  1. Per attivare il monitoraggio della posizione nella tua app, crea in MapsActivity un metodo denominato enableMyLocation() che non accetta argomenti e non restituisca nulla. All'interno, verifica la presenza dell'autorizzazione ACCESS_FINE_LOCATION. Se l'autorizzazione viene concessa, abilita il livello di localizzazione. In caso contrario, richiedi l'autorizzazione.
private fun enableMyLocation() {
   if (isPermissionGranted()) {
       map.isMyLocationEnabled = true 
   }
   else {
       ActivityCompat.requestPermissions(
           this,
           arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
           REQUEST_LOCATION_PERMISSION
       )
   }
}
  1. Chiama enableMyLocation() dal callback onMapReady() per attivare il livello di località.
override fun onMapReady(googleMap: GoogleMap) {
   ...
   enableMyLocation()
}
  1. Esegui l'override del metodo onRequestPermissionsResult(). Verifica che requestCode sia uguale a REQUEST_LOCATION_PERMISSION. In tal caso, significa che l'autorizzazione è stata concessa. Se l'autorizzazione viene concessa, controlla anche se l'array grantResults contiene PackageManager.PERMISSION_GRANTED nel primo slot. In tal caso, chiama enableMyLocation().
override fun onRequestPermissionsResult(
   requestCode: Int,
   permissions: Array<String>,
   grantResults: IntArray) {
   if (requestCode == REQUEST_LOCATION_PERMISSION) {
       if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
           enableMyLocation()
       }
   }
}
  1. Esegui l'app. Dovrebbe essere visualizzata una finestra di dialogo che richiede l'accesso alla posizione del dispositivo. Concedi l'autorizzazione.

da7e23e00ec762c1.png

La mappa ora mostra la posizione attuale del dispositivo mediante un punto blu. Vedrai che è presente un pulsante per la posizione. Se sposti la mappa lontano dalla tua posizione e fai clic su questo pulsante, la mappa viene centrata sulla posizione del dispositivo.

5b12eda7f467bc2f.png

9. Codice soluzione

Scarica il codice per il codelab completato.

$  git clone https://github.com/googlecodelabs/android-kotlin-geo-maps

In alternativa, puoi scaricare il repository come file ZIP, decomprimerlo e aprirlo in Android Studio.

10. Riepilogo

Complimenti! Hai aggiunto una mappa Google a un'app Android Kotlin e l'hai assegnato.

11. Scopri di più

Documentazione per gli sviluppatori Android:

Documentazione di riferimento:

12. Codelab successivo

Per i link ad altri codelab di questo corso, consulta la pagina di destinazione avanzata dei codelab Android in Kotlin.