Informazioni su questo codelab
1. Prima di iniziare
Scopri come utilizzare Google Maps Platform e l'SDK Places per Android per presentare agli utenti un elenco di luoghi per identificare le loro posizioni attuali.
Prerequisiti
- Competenze di base di Java
In questo lab proverai a:
- Aggiungi una mappa a un'app Android.
- Utilizza le autorizzazioni di accesso alla posizione per geolocalizzare l'utente.
- Recupera luoghi vicino alla posizione corrente dell'utente.
- Presenta i luoghi probabili all'utente per identificare la sua posizione corrente.
Cosa devi creare
Puoi creare la tua app Android da zero, ma puoi scaricare il codice campione per confrontarlo durante il debug. Scarica il codice di esempio da GitHub o, se hai impostato Git per l'uso dalla riga di comando, inserisci quanto segue:
git clone https://github.com/googlecodelabs/current-place-picker-android.git
Se riscontri problemi (bug di codice, errori grammaticali, parole non chiare o altro) mentre lavori al codelab, segnala il problema tramite il link Segnala un errore nell'angolo in basso a sinistra del codelab.
2. Per iniziare
Prima di iniziare questo codelab, devi configurare quanto segue:
Android Studio
Scarica Android Studio da https://developer.android.com/studio.
Se hai già Android Studio, assicurati di avere la versione più recente facendo clic su Android Studio > Verifica disponibilità di aggiornamenti....
Questo lab è stato scritto con Android Studio 3.4.
SDK Android
In Android Studio puoi configurare gli SDK desiderati utilizzando SDK Manager. Questo lab utilizza l'SDK Android Q.
- Dalla schermata di benvenuto di Android Studio, fai clic su Configure (Configura) > SDK Manager.
- Seleziona la casella di controllo SDK che preferisci, poi fai clic su Applica.
Se non hai ancora l'SDK, viene avviato il download dell'SDK sul tuo computer.
Google Play Services
Devi anche installare Google Play Services da SDK Manager.
- Fai clic sulla scheda Strumenti SDK e seleziona la casella di controllo Google Play Services.
Aggiorna se lo stato è Aggiornamento disponibile.
3. Prepara l'emulatore
Per eseguire l'app, puoi connettere il tuo dispositivo o utilizzare l'emulatore Android.
Se utilizzi il tuo dispositivo, vai alla sezione Istruzioni per i dispositivi reali: aggiorna Google Play Services alla fine di questa pagina.
Aggiungi un emulatore
- Nella schermata di benvenuto di Android Studio, fai clic su Configure (Configura) > AVD Manager (Gestione AVD).
Viene visualizzata la finestra di dialogo Android Virtual Device Manager.
- Fai clic su Crea dispositivo virtuale... per aprire un elenco di dispositivi tra cui scegliere.
- Scegli un dispositivo con l'icona Riproduci
nella colonna Play Store e fai clic su Avanti.
Vedrai un insieme di immagini di sistema che puoi installare. Se Q ha come target Android 9.+ (Google Play) e ha la parola Scarica, fai clic su Scarica.
- Fai clic su Avanti per assegnare un nome al dispositivo virtuale, quindi fai clic su Fine.
Tornerai all'elenco I tuoi dispositivi virtuali.
- Fai clic su Avvia
accanto al nuovo dispositivo:
Dopo qualche istante, si apre l'emulatore.
Istruzioni per l'emulatore: aggiorna Google Play Services
- Una volta avviato l'emulatore, fai clic su ... nella barra di navigazione visualizzata**.**
In questo modo si apre la finestra di dialogo Controlli estesi.
- Fai clic su Google Play nel menu.
Se è disponibile un aggiornamento, fai clic su Aggiorna.
- Accedi all'emulatore con un Account Google.
Puoi utilizzare il tuo o creare un nuovo account senza costi per mantenere i test separati dalle tue informazioni personali.
Google Play si apre quindi in Google Play Services.
- Fai clic su Aggiorna per scaricare l'ultima versione di Google Play Services.
Se ti viene chiesto di completare la creazione dell'account e di aggiungere un'opzione di pagamento, fai clic su Ignora.
Imposta posizione nell'emulatore
- Una volta avviato l'emulatore, digita "mappe". Nella barra di ricerca della schermata Home viene visualizzata l'icona dell'app Google Maps.
- Fai clic sull'icona per avviare l'app.
Viene visualizzata una mappa predefinita.
- In basso a destra sulla mappa, fai clic su La tua posizione
.
Ti viene chiesto di autorizzare il telefono a usare la posizione.
- Fai clic su ... per aprire il menu Controlli estesi.
- Fai clic sulla scheda Località.
- Inserisci latitudine e longitudine.
Inserisci tutto ciò che ti piace, ma assicurati che si trovi in una zona con molti luoghi.
(Usa Latitude 20.7818 e Longitude -156.4624 per la città di Kihei alle Maui alle Hawaii per replicare i risultati di questo codelab.)
- Fai clic su Invia e la mappa verrà aggiornata con questa località.
Ora puoi eseguire la tua app e testarla con la posizione.
Istruzioni per dispositivi reali: aggiorna Google Play Services
Se utilizzi un dispositivo Android reale, procedi nel seguente modo:
- Utilizza la barra di ricerca nella schermata Home per cercare e aprire Google Play Services.
- Fai clic su More Details (Ulteriori dettagli).
Se disponibile, fai clic su Aggiorna.
4. Creare la shell dell'app con un'attività di Google Maps
- Nella schermata di benvenuto di Android Studio, seleziona Avvia un nuovo progetto Android Studio.
- Nella scheda Telefono e tablet, seleziona Attività su Google Maps.
Viene visualizzata la finestra di dialogo Configura il tuo progetto. Qui puoi assegnare un nome alla tua app e creare il pacchetto in base al tuo dominio.
Di seguito sono riportate le impostazioni di un'app chiamata Luogo attuale, che corrisponde al pacchetto com.google.codelab.currentplace
.
- Scegli Java come lingua e seleziona Utilizza artefatti androidx*.
Mantieni i valori predefiniti per le altre impostazioni.
- Fai clic su Fine.
5. Aggiungere dipendenze dei servizi Google al file di build Gradle
Per accedere alle autorizzazioni di accesso alla posizione in Android, devi disporre dell'API Google Location and Recognition API di Google Play Services. Per ulteriori informazioni sull'aggiunta di questa e di altre API Google Play Services, vedi Configurare Google Play Services.
In genere, i progetti Android Studio hanno due file build.gradle
. Uno è per il progetto generale e uno per l'app. Se hai l'Explorer di progetto Android Studio nella visualizzazione Android, li vedi entrambi nella cartella Gradle Scripts
. Per aggiungere servizi Google devi modificare il file build.gradle (Module: app)
.
- Aggiungi due righe alla sezione
dependencies
per aggiungere i servizi Google per la località e l'API Places (codice di esempio nel contesto).
build.gradle (modulo: app)
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.google.codelab.currentplace"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'com.google.android.gms:play-services-maps:16.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
implementation 'com.google.android.gms:play-services-location:16.0.0'
implementation 'com.google.android.libraries.places:places:1.1.0'
}
6. Abilita le API Google Maps Platform e ottieni una chiave API
Per il seguente passaggio di attivazione , devi attivare l'SDK Maps per Android e l'API Places.
Configurare Google Maps Platform
Se non hai ancora un account Google Cloud Platform e un progetto con la fatturazione abilitata, consulta la guida Utilizzo di Google Maps Platform per creare un account di fatturazione e un progetto.
- In Cloud Console, fai clic sul menu a discesa del progetto e seleziona il progetto che vuoi utilizzare per questo codelab.
- Abilita le API e gli SDK di Google Maps Platform richiesti per questo codelab in Google Cloud Marketplace. Per farlo, segui la procedura descritta in questo video o in questa documentazione.
- Genera una chiave API nella pagina Credentials di Cloud Console. Puoi seguire la procedura descritta in questo video o in questa documentazione. Tutte le richieste a Google Maps Platform richiedono una chiave API.
Copia la chiave API appena creata. Torna ad Android Studio e cerca il file google_maps_api.xml
in Android > app > res > value.
Sostituisci YOUR_KEY_HERE
con la chiave API che hai copiato.
La tua app è configurata.
7. Modificare il file di layout
- In Esplora progetto, apri il file
activity_maps.xml
in Android >app
>res
>layout
.
- Vedrai l'interfaccia utente di base aperta sulla destra dello schermo, con le schede nella parte inferiore che ti permettono di selezionare l'Editor di progettazione o Testo per il tuo layout. Seleziona Testo e sostituisci l'intero contenuto del file di layout con questo:
activity_maps.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:minHeight="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:titleTextColor="@android:color/white"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="349dp"
tools:context=".MapsActivity" />
<ListView
android:id="@+id/listPlaces"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
In questo modo avrai un'interfaccia utente simile alla seguente:
8. Configurare la barra dell'app
Per fare in modo che l'utente facciano clic su un pulsante per scegliere il luogo in cui si trova attualmente, aggiungi una barra delle app con un'icona che indica la posizione corrente dell'utente e la posizione in cui si trovano nelle vicinanze. L'aspetto sarà simile al seguente:
Su un telefono viene mostrata solo l'icona. Su un tablet con più spazio, è incluso anche il testo.
Creare l'icona
- In Esplora progetto, fai clic su Android > app, quindi fai clic con il pulsante destro del mouse sulla cartella res e seleziona Nuovo > asset immagine.
Si apre Asset Studio.
- Nel menu Tipo di icona, fai clic su Barra delle azioni e Icone.
- Assegna un nome all'asset
ic_geolocate
. - Seleziona Clip art come tipo di risorsa**.
- Fai clic sull'immagine accanto a Clip art.
Viene visualizzata la finestra Seleziona icona.
- Scegli un'icona.
Puoi utilizzare la barra di ricerca per trovare le icone correlate all'intenzione.
- Cerca
location
e scegli un'icona relativa alla località.
L'icona La mia posizione corrisponde a quella utilizzata nell'app Google Maps quando un utente vuole agganciare la fotocamera alla propria posizione corrente.
- Fai clic su OK > Next > Finish (Fine) e conferma che è presente una nuova cartella chiamata
drawable
contenente i nuovi file dell'icona.
Aggiungi risorse stringa
- In Esplora progetto, fai clic su Android > app > res > values e apri il file
strings.xml
. - Aggiungi le seguenti righe dopo
<string name="title_activity_maps">Map</string>
:
stringhe.xml
<string name="action_geolocate">Pick Place</string>
<string name="default_info_title">Default Location</string>
<string name="default_info_snippet">No places found, because location permission is disabled.</string>
La prima riga viene utilizzata nella barra dell'app quando c'è spazio per includere un'etichetta di testo accanto all'icona. Gli altri vengono utilizzati per gli indicatori che aggiungi alla mappa.
A questo punto il codice nel file ha il seguente aspetto:
<resources>
<string name="app_name">Current Place</string>
<string name="title_activity_maps">Map</string>
<string name="action_geolocate">Pick Place</string>
<string name="default_info_title">Default Location</string>
<string name="default_info_snippet">No places found, because location permission is disabled.</string>
</resources>
Aggiungere la barra dell'app
- In Esplora progetto, fai clic su Android > app, quindi fai clic con il pulsante destro del mouse sulla cartella
res
e seleziona Nuovo > directory per creare una nuova sottodirectory inapp/src/main/res
. - Assegna alla directory il nome
menu
. - Fai clic con il pulsante destro del mouse sulla cartella
menu
e seleziona Nuovo > File. - Assegna al file il nome
menu.xml
. - Incolla questo codice:
menu.xml
<?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">
<!-- "Locate me", should appear as action button if possible -->
<item
android:id="@+id/action_geolocate"
android:icon="@drawable/ic_geolocate"
android:title="@string/action_geolocate"
app:showAsAction="always|withText" />
</menu>
Aggiorna lo stile della barra delle app
- In Esplorazione progetto, espandi il file Android >
app
>res
>values
e apri il filestyles.xml
. - Nel tag
<style>
, modifica la proprietà principale in modo che sia"Theme.AppCompat.NoActionBar"
. - Osserva la proprietà
name
, che utilizzerai nel passaggio successivo.
styles.xml
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
Aggiorna il tema dell'app in AndroidManifest.xml
- Fai clic su Android >
app
>manifests
e apri il fileAndroidManifest.xml
. - Trova la riga
android:theme
e modifica o conferma il valore in@style/AppTheme
.
AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
Ora puoi iniziare la programmazione.
9. Inizializza l'app
- In Esplora progetto, trova il file
MapsActivity.java
.
Si trova nella cartella corrispondente al pacchetto che hai creato per la tua app nel passaggio 1.
- Apri il file e apri l'editor di codice Java.
Importare l'SDK Places e altre dipendenze
Aggiungi queste righe nella parte superiore di MapsActivity.java
, sostituendo le istruzioni di importazione esistenti.
Includono le importazioni esistenti e ne aggiungono molte altre utilizzate nel codice in questo codelab.
MapsActivity.java
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.libraries.places.api.Places;
import com.google.android.libraries.places.api.model.Place;
import com.google.android.libraries.places.api.model.PlaceLikelihood;
import com.google.android.libraries.places.api.net.FindCurrentPlaceRequest;
import com.google.android.libraries.places.api.net.FindCurrentPlaceResponse;
import com.google.android.libraries.places.api.net.PlacesClient;
import java.util.Arrays;
import java.util.List;
Aggiornare la firma del corso
L'API Places utilizza i componenti AndroidX per il supporto compatibile con le versioni precedenti, quindi devi definirla per estendere il AppCompatActivity
. Sostituisce l'estensione FragmentActivity
definita per impostazione predefinita per un'attività su Maps.
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
Aggiungere variabili di classe
In seguito, dichiara le varie variabili del corso utilizzate in diversi metodi. Questi includono gli elementi dell'interfaccia utente e i codici di stato. Questi valori dovrebbero essere appena sotto la dichiarazione della variabile per GoogleMap mMap
.
// New variables for Current Place picker
private static final String TAG = "MapsActivity";
ListView lstPlaces;
private PlacesClient mPlacesClient;
private FusedLocationProviderClient mFusedLocationProviderClient;
// The geographical location where the device is currently located. That is, the last-known
// location retrieved by the Fused Location Provider.
private Location mLastKnownLocation;
// A default location (Sydney, Australia) and default zoom to use when location permission is
// not granted.
private final LatLng mDefaultLocation = new LatLng(-33.8523341, 151.2106085);
private static final int DEFAULT_ZOOM = 15;
private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
private boolean mLocationPermissionGranted;
// Used for selecting the Current Place.
private static final int M_MAX_ENTRIES = 5;
private String[] mLikelyPlaceNames;
private String[] mLikelyPlaceAddresses;
private String[] mLikelyPlaceAttributions;
private LatLng[] mLikelyPlaceLatLngs;
Aggiornare il metodo onCreate
Dovrai aggiornare il metodo onCreate
per gestire le autorizzazioni dell'utente runtime per i servizi di geolocalizzazione, configurare gli elementi dell'interfaccia utente e creare il client API Places.
Aggiungi le seguenti righe di codice sulla barra degli strumenti delle azioni, la configurazione delle viste e il client Places alla fine del metodo onCreate()
esistente.
MapsActivity.java onCreate()
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
//
// PASTE THE LINES BELOW THIS COMMENT
//
// Set up the action toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Set up the views
lstPlaces = (ListView) findViewById(R.id.listPlaces);
// Initialize the Places client
String apiKey = getString(R.string.google_maps_key);
Places.initialize(getApplicationContext(), apiKey);
mPlacesClient = Places.createClient(this);
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
}
Aggiungere il codice per il menu della barra dell'app
Questi due metodi consentono di aggiungere il menu della barra delle applicazioni (con un singolo elemento, l'icona Scegli luogo) e di gestire i clic dell'utente.
Copia questi due metodi nel file dopo il metodo onCreate
.
MapsActivity.java onCreateOptionsMenu() e onOptionsItemSelected()
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_geolocate:
// COMMENTED OUT UNTIL WE DEFINE THE METHOD
// Present the current place picker
// pickCurrentPlace();
return true;
default:
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
return super.onOptionsItemSelected(item);
}
}
Prova
- Da Android Studio, fai clic su Esegui o Esegui menu > esegui "app'.
- Ti verrà chiesto di selezionare il target di deployment. L'emulatore in esecuzione dovrebbe essere presente in questo elenco. Selezionala e Android Studio esegue il deployment dell'app nell'emulatore.
Dopo qualche istante, l'app viene avviata. Vedrai la mappa centrata su Sydney, in Australia, con un singolo pulsante e un elenco di luoghi disabitati.
Lo stato attivo della mappa non si sposta nella posizione dell'utente, a meno che non richiedi l'autorizzazione ad accedere alla posizione del dispositivo.
10. Richiedere e gestire le autorizzazioni di accesso alla posizione
Richiedere le autorizzazioni di accesso alla posizione quando la mappa è pronta
- Definisci un metodo chiamato
getLocationPermission
che richiede le autorizzazioni utente.
Incolla questo codice sotto il metodo onOptionsSelected
che hai appena creato.
MapsActivity.java getLocationPermission()
private void getLocationPermission() {
/*
* Request location permission, so that we can get the location of the
* device. The result of the permission request is handled by a callback,
* onRequestPermissionsResult.
*/
mLocationPermissionGranted = false;
if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
} else {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
}
- Aggiungi due righe alla fine del metodo
onMapReady
esistente per attivare i controlli zoom e richiedere all'utente le autorizzazioni di accesso alla posizione.
MapsActivity.java onMapReady()
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
//
// PASTE THE LINES BELOW THIS COMMENT
//
// Enable the zoom controls for the map
mMap.getUiSettings().setZoomControlsEnabled(true);
// Prompt the user for permission.
getLocationPermission();
}
Gestire il risultato dalle autorizzazioni richieste
Quando l'utente risponde alla finestra di dialogo per la richiesta di autorizzazione, il callback viene chiamato da Android.
Incolla questo codice dopo il metodo getLocationPermission()
:
MapsActivity.java onRequestPermissionsResult()
/**
* Handles the result of the request for location permissions
*/
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String permissions[],
@NonNull int[] grantResults) {
mLocationPermissionGranted = false;
switch (requestCode) {
case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
}
}
}
}
11. Individuare la posizione attuale e recuperare i luoghi probabili
Quando l'utente fa clic su Scegli luogo nella barra dell'app, l'app chiama il metodo pickCurrentPlace()
, che chiama il metodo getDeviceLocation()
definito in precedenza. Il metodo getDeviceLocation
chiama un altro metodo, getCurrentPlaceLikelihoods,
dopo aver recuperato la posizione più recente del dispositivo.
Chiama l'API FindCurrentPlace e gestisci la risposta
getCurrentPlaceLikelihoods
crea un elemento findCurrentPlaceRequest
e chiama l'attività Places findCurrentPlace
. Se l'attività ha esito positivo, restituisce un findCurrentPlaceResponse
, che contiene un elenco di oggetti placeLikelihood
. Ognuno di questi elementi ha una serie di proprietà, tra cui il nome e l'indirizzo del luogo, e la probabilità che tu ti trovi in quel luogo (un valore doppio compreso tra 0 e 1). Questo metodo gestisce la risposta creando elenchi di dettagli dei luoghi da placeLikelihoods
.
Questo codice esegue l'iterazione tra le cinque posizioni con maggiori probabilità e aggiunge quelle con una probabilità maggiore di 0 a un elenco che viene poi visualizzato. Se vuoi che vengano visualizzati più o meno di cinque, modifica la costante M_MAX_ENTRIES
.
Incolla questo codice dopo il metodo onMapReady
.
MapsActivity.java getCurrentPlaceLikelihoods()
private void getCurrentPlaceLikelihoods() {
// Use fields to define the data types to return.
List<Place.Field> placeFields = Arrays.asList(Place.Field.NAME, Place.Field.ADDRESS,
Place.Field.LAT_LNG);
// Get the likely places - that is, the businesses and other points of interest that
// are the best match for the device's current location.
@SuppressWarnings("MissingPermission") final FindCurrentPlaceRequest request =
FindCurrentPlaceRequest.builder(placeFields).build();
Task<FindCurrentPlaceResponse> placeResponse = mPlacesClient.findCurrentPlace(request);
placeResponse.addOnCompleteListener(this,
new OnCompleteListener<FindCurrentPlaceResponse>() {
@Override
public void onComplete(@NonNull Task<FindCurrentPlaceResponse> task) {
if (task.isSuccessful()) {
FindCurrentPlaceResponse response = task.getResult();
// Set the count, handling cases where less than 5 entries are returned.
int count;
if (response.getPlaceLikelihoods().size() < M_MAX_ENTRIES) {
count = response.getPlaceLikelihoods().size();
} else {
count = M_MAX_ENTRIES;
}
int i = 0;
mLikelyPlaceNames = new String[count];
mLikelyPlaceAddresses = new String[count];
mLikelyPlaceAttributions = new String[count];
mLikelyPlaceLatLngs = new LatLng[count];
for (PlaceLikelihood placeLikelihood : response.getPlaceLikelihoods()) {
Place currPlace = placeLikelihood.getPlace();
mLikelyPlaceNames[i] = currPlace.getName();
mLikelyPlaceAddresses[i] = currPlace.getAddress();
mLikelyPlaceAttributions[i] = (currPlace.getAttributions() == null) ?
null : TextUtils.join(" ", currPlace.getAttributions());
mLikelyPlaceLatLngs[i] = currPlace.getLatLng();
String currLatLng = (mLikelyPlaceLatLngs[i] == null) ?
"" : mLikelyPlaceLatLngs[i].toString();
Log.i(TAG, String.format("Place " + currPlace.getName()
+ " has likelihood: " + placeLikelihood.getLikelihood()
+ " at " + currLatLng));
i++;
if (i > (count - 1)) {
break;
}
}
// COMMENTED OUT UNTIL WE DEFINE THE METHOD
// Populate the ListView
// fillPlacesList();
} else {
Exception exception = task.getException();
if (exception instanceof ApiException) {
ApiException apiException = (ApiException) exception;
Log.e(TAG, "Place not found: " + apiException.getStatusCode());
}
}
}
});
}
Sposta la fotocamera della mappa nella posizione corrente del dispositivo
Se l'utente concede l'autorizzazione, l'app recupera l'ultima posizione dell'utente e sposta la fotocamera al centro dell'utente.
Se l'utente nega l'autorizzazione, l'app si limita a spostare la fotocamera nella posizione predefinita definita tra le costanti all'inizio di questa pagina (nel codice di esempio, si tratta di Sydney, Australia).
Incolla questo codice dopo il metodo getPlaceLikelihoods()
:
MapsActivity.java getDeviceLocation()
private void getDeviceLocation() {
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
try {
if (mLocationPermissionGranted) {
Task<Location> locationResult = mFusedLocationProviderClient.getLastLocation();
locationResult.addOnCompleteListener(this, new OnCompleteListener<Location>() {
@Override
public void onComplete(@NonNull Task<Location> task) {
if (task.isSuccessful()) {
// Set the map's camera position to the current location of the device.
mLastKnownLocation = task.getResult();
Log.d(TAG, "Latitude: " + mLastKnownLocation.getLatitude());
Log.d(TAG, "Longitude: " + mLastKnownLocation.getLongitude());
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(mLastKnownLocation.getLatitude(),
mLastKnownLocation.getLongitude()), DEFAULT_ZOOM));
} else {
Log.d(TAG, "Current location is null. Using defaults.");
Log.e(TAG, "Exception: %s", task.getException());
mMap.moveCamera(CameraUpdateFactory
.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
}
getCurrentPlaceLikelihoods();
}
});
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage());
}
}
Verifica le autorizzazioni di accesso alla posizione quando l'utente fa clic su Scegli luogo
Quando l'utente tocca Scegli luogo, questo metodo controlla le autorizzazioni di accesso alla posizione e chiede l'autorizzazione se non è stato concesso.
Se l'utente ha concesso l'autorizzazione, il metodo chiama getDeviceLocation
per avviare il processo di recupero delle posizioni correnti.
- Aggiungi questo metodo dopo il giorno
getDeviceLocation()
:
MapsActivity.java pickCurrentPlace()
private void pickCurrentPlace() {
if (mMap == null) {
return;
}
if (mLocationPermissionGranted) {
getDeviceLocation();
} else {
// The user has not granted permission.
Log.i(TAG, "The user did not grant location permission.");
// Add a default marker, because the user hasn't selected a place.
mMap.addMarker(new MarkerOptions()
.title(getString(R.string.default_info_title))
.position(mDefaultLocation)
.snippet(getString(R.string.default_info_snippet)));
// Prompt the user for permission.
getLocationPermission();
}
}
- Ora che hai definito
pickCurrentPlace
, trova la riga inonOptionsItemSelected()
che chiamapickCurrentPlace
e annulla il commento.
MapsActivity.java onOptionItemSelected()
case R.id.action_geolocate:
// COMMENTED OUT UNTIL WE DEFINE THE METHOD
// Present the Current Place picker
pickCurrentPlace();
return true;
Prova
Se esegui l'app adesso e tocchi Scegli luogo, dovrebbero essere richieste le autorizzazioni di accesso alla posizione.
- Se autorizzi l'autorizzazione, questa preferenza verrà salvata e non ti verrà chiesto. Se neghi l'autorizzazione, ricevi un nuovo avviso quando tocchi il pulsante.
- Anche se
getPlaceLikelihoods
ha recuperato i probabili luoghi correnti,ListView
non li mostra ancora. In Android Studio, puoi fare clic su ⌘6 per controllare nei log di Logcat le istruzioni con l'etichetta MapsActivity da verificare che i nuovi metodi funzionino correttamente. - Se hai concesso l'autorizzazione, i log includono un'istruzione per
Latitude:
e un'istruzione perLongitude:
che mostra la posizione rilevata del dispositivo. Se hai utilizzato Google Maps e il menu esteso dell'emulatore in precedenza per specificare una posizione per l'emulatore, queste dichiarazioni mostrano la posizione. - Se la chiamata al numero
findCurrentPlace
ha avuto esito positivo, i log includono cinque istruzioni che stampano i nomi e le posizioni dei cinque luoghi che con maggiori probabilità vengono visualizzati.
12. Completa il selettore dei luoghi attuali
Configurazione di un gestore per i luoghi selezionati
Vediamo cosa succede quando l'utente fa clic su un elemento nel ListView
. Per confermare la scelta dell'utente del luogo in cui si trova attualmente, puoi aggiungere un indicatore alla mappa. Se l'utente fa clic sull'indicatore, viene visualizzata una finestra informativa che mostra il nome e l'indirizzo del luogo.
Incolla questo gestore dei clic dopo il metodo pickCurrentPlace
.
MapsActivity.java listClickedHandler
private AdapterView.OnItemClickListener listClickedHandler = new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
// position will give us the index of which place was selected in the array
LatLng markerLatLng = mLikelyPlaceLatLngs[position];
String markerSnippet = mLikelyPlaceAddresses[position];
if (mLikelyPlaceAttributions[position] != null) {
markerSnippet = markerSnippet + "\n" + mLikelyPlaceAttributions[position];
}
// Add a marker for the selected place, with an info window
// showing information about that place.
mMap.addMarker(new MarkerOptions()
.title(mLikelyPlaceNames[position])
.position(markerLatLng)
.snippet(markerSnippet));
// Position the map's camera at the location of the marker.
mMap.moveCamera(CameraUpdateFactory.newLatLng(markerLatLng));
}
};
Compilare la ListView
Ora che hai creato un elenco dei luoghi che molto probabilmente sta visitando l'utente, puoi presentare queste opzioni all'utente in ListView
. puoi anche impostare il listener di clic su ListView
in modo che utilizzi il gestore dei clic appena definito.
Incolla questo metodo dopo il gestore dei clic:
MapsActivity.java FillLuoghiList()
private void fillPlacesList() {
// Set up an ArrayAdapter to convert likely places into TextViews to populate the ListView
ArrayAdapter<String> placesAdapter =
new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mLikelyPlaceNames);
lstPlaces.setAdapter(placesAdapter);
lstPlaces.setOnItemClickListener(listClickedHandler);
}
Ora che è stato definito fillPlacesList
, trova la riga verso la fine del findPlaceLikelihoods
che chiama fillPlacesList
e annulla il commento.
MapsActivity.java FillPlaceLikelihoods()
// COMMENTED OUT UNTIL WE DEFINE THE METHOD
// Populate the ListView
fillPlacesList();
Ecco tutto il codice necessario per il selettore dei luoghi attuali.
13. Esegui l'app
Testare la scelta di un luogo
- Esegui di nuovo l'app.
Questa volta, quando tocchi Scegli luogo l'app completa l'elenco con i luoghi denominati vicino al luogo. Vicino a questa località di Maui si trovano luoghi come l'Hawaiian Shave Ice e il Sugar Beach Bake Shop. Dato che i vari luoghi sono molto vicini alle coordinate di posizione, questo è un elenco di posti in cui potresti trovarti.
- Fai clic sul nome di un luogo nella
ListView
.
Dovresti vedere un indicatore aggiunto alla mappa.
- Tocca l'indicatore.
Puoi visualizzare i dettagli del luogo.
Testare una località diversa
Se vuoi cambiare la tua posizione e stai utilizzando l'emulatore, la posizione del dispositivo non viene aggiornata automaticamente quando aggiorni le coordinate della posizione nel menu esteso dell'emulatore.
Per aggirare il problema, segui questi passaggi per utilizzare l'app nativa di Google Maps per forzare gli aggiornamenti alla posizione dell'emulatore:
- Apri Google Maps.
- Tocca ... > Posizione per modificare la latitudine e la longitudine in base alle nuove coordinate, quindi tocca Invia.
- Ad esempio, puoi utilizzare Latitudine: 49.2768 e Longitudine: -123.1142 per impostare la posizione al centro di Vancouver, Canada.
- Verifica che Google Maps sia stato rinnovato in base alle nuove coordinate. Per richiedere la ricentrazione, potresti dover toccare il pulsante La mia posizione nell'app Google Maps.
- Torna all'app Luogo corrente e tocca Scegli luogo per visualizzare la mappa sulle nuove coordinate e visualizzare un nuovo elenco di luoghi attuali.
e il gioco è fatto. Hai creato un'app semplice che controlla i luoghi nella posizione attuale e ti dà la probabilità di vedere quelli in cui ti trovi. Buon divertimento!
Ora continua e passa all'app con le modifiche che hai apportato per completare questo passaggio bonus!
14. Passaggi successivi
Per impedire il furto della chiave API, devi proteggerla in modo che solo la tua app Android possa utilizzarla. Se non vengono applicate limitazioni, chiunque abbia il tuo token potrebbe utilizzarlo per chiamare le API di Google Maps Platform e farti pagare.
Ottieni il certificato SHA-1
Questa operazione è necessaria in un secondo momento per limitare le chiavi API. Di seguito è riportato un insieme di istruzioni per ottenere il certificato di debug.
Per Linux o macOS, apri una finestra del terminale e inserisci quanto segue:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
Per Windows Vista e Windows 7, esegui il comando seguente:
keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
Dovresti vedere un output simile al seguente:
Alias name: androiddebugkey Creation date: Jan 01, 2013 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Android Debug, O=Android, C=US Issuer: CN=Android Debug, O=Android, C=US Serial number: 4aa9b300 Valid from: Mon Jan 01 08:04:04 UTC 2013 until: Mon Jan 01 18:04:04 PST 2033 Certificate fingerprints: MD5: AE:9F:95:D0:A6:86:89:BC:A8:70:BA:34:FF:6A:AC:F9 SHA1: BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75 Signature algorithm name: SHA1withRSA Version: 3
La riga che inizia in SHA1 contiene l'impronta SHA-1 del certificato. L'impronta è la sequenza di 20 numeri esadecimali a due cifre separati da due punti.
Quando è tutto pronto per rilasciare un'app, segui le istruzioni riportate in questa documentazione per recuperare il certificato di rilascio.
Aggiungere limitazioni alla chiave API
- In Cloud Console, vai ad API e servizi > Credenziali.
La chiave utilizzata per questa app deve essere elencata in Chiavi API.
- Fai clic su
per modificare le impostazioni della chiave.
- Nella pagina della chiave API, dopo Limitazioni chiave, imposta le Limitazioni dell'applicazione procedendo nel seguente modo:
- Seleziona App Android e segui le istruzioni.
- Fai clic su Aggiungi un elemento.
- Inserisci il nome del pacchetto e l'impronta digitale del certificato SHA-1 (recuperato nella sezione precedente).
Ad esempio:
com.google.codelab.currentplace
BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75s
- Per una maggiore protezione, imposta le restrizioni dell'API come descritto di seguito.
- Dopo le limitazioni dell'API, scegli Limita la chiave.
- Seleziona l'SDK Maps per Android e per l'API Places.
- Fai clic su Fine e Salva.
15. Complimenti
Hai creato un'app semplice che controlla la posizione più probabile nella posizione corrente e aggiunge un indicatore alla mappa per il luogo selezionato.
Scopri di più
- Per accelerare lo sviluppo, utilizza la libreria di mappe di Maps SDK for Android. Queste utilità consentono di svolgere alcune delle attività più comuni per le app che utilizzano Google Maps Platform.
- Per altri esempi di codice che mostrano la maggior parte delle funzionalità degli SDK Google Maps Platform per Android, clona i repository per gli esempi di SDK di Maps per Android e SDK Places per Android.
- Per scoprire come gestire le autorizzazioni di accesso alla posizione in tre stati in Android Q, completa il codelab Ricevi gli aggiornamenti della posizione in Android con Kotlin.