1. Zanim zaczniesz
Dowiedz się, jak za pomocą Google Maps Platform i pakietu SDK Miejsc na Androida wyświetlać użytkownikom listę miejsc, aby mogli określić swoją bieżącą lokalizację.
Wymagania wstępne
- podstawowe umiejętności w zakresie Javy,
Jakie zadania wykonasz
- Dodaj mapę do aplikacji na Androida.
- Używaj uprawnień do lokalizacji, aby określać lokalizację geograficzną użytkownika.
- Pobieranie miejsc w pobliżu bieżącej lokalizacji użytkownika.
- Wyświetlaj użytkownikowi prawdopodobne miejsca, aby mógł określić swoją bieżącą lokalizację.
Co utworzysz
Aplikację na Androida tworzysz od zera, ale podczas debugowania możesz pobrać kod przykładowy, aby go porównać. Pobierz przykładowy kod z GitHuba lub, jeśli masz skonfigurowany Git do używania w wierszu poleceń, wpisz to polecenie:
git clone https://github.com/googlecodelabs/current-place-picker-android.git
Jeśli podczas wykonywania tego laboratorium napotkasz jakiekolwiek problemy (błędy w kodzie, błędy gramatyczne, niejasne sformułowania lub inne), zgłoś je, klikając link Zgłoś błąd w lewym dolnym rogu laboratorium.
2. Rozpocznij
Zanim zaczniesz wykonywać zadania z tego ćwiczenia, musisz skonfigurować te elementy:
Android Studio
Pobierz Android Studio ze strony https://developer.android.com/studio.
Jeśli masz już Android Studio, sprawdź, czy korzystasz z najnowszej wersji. W tym celu kliknij Android Studio > Sprawdź dostępność aktualizacji….
Te ćwiczenia zostały opracowane w Androidzie Studio 3.4.
Android SDK
W Android Studio możesz skonfigurować wybrane pakiety SDK za pomocą Menedżera SDK. W tym module używamy pakietu Android Q SDK.
- Na ekranie powitalnym Android Studio kliknij Configure (Skonfiguruj) > SDK Manager (Menedżer pakietów SDK).
- Zaznacz pole wyboru odpowiedniego pakietu SDK, a potem kliknij Zastosuj.
Jeśli nie masz jeszcze pakietu SDK, rozpocznie się jego pobieranie na Twój komputer.
Usługi Google Play
W Menedżerze pakietów SDK musisz też zainstalować Usługi Google Play.
- Kliknij kartę Narzędzia SDK i zaznacz pole wyboru Usługi Google Play.
Zaktualizuj, jeśli stan to Dostępna aktualizacja.
3. Przygotowywanie emulatora
Aby uruchomić aplikację, możesz podłączyć własne urządzenie lub użyć emulatora Androida.
Jeśli używasz własnego urządzenia, przejdź do sekcji Instrukcje dotyczące prawdziwego urządzenia: aktualizowanie Usług Google Play na końcu tej strony.
Dodawanie emulatora
- Na ekranie powitalnym Android Studio kliknij Configure (Skonfiguruj) > AVD Manager (Menedżer AVD).
Otworzy się okno Android Virtual Device Manager (Menedżer wirtualnych urządzeń z Androidem).
- Kliknij Utwórz urządzenie wirtualne…, aby otworzyć listę urządzeń, z której możesz wybrać urządzenie.
- Wybierz urządzenie z ikoną Play
w kolumnie Sklep Play i kliknij Dalej.
Zobaczysz zestaw obrazów systemu, które możesz zainstalować. Jeśli obok kierowania Q na Androida 9.+ (Google Play) znajduje się słowo Pobierz, kliknij Pobierz.
- Kliknij Dalej, aby nadać urządzeniu wirtualnemu nazwę, a potem kliknij Zakończ.
Wrócisz do listy Twoje urządzenia wirtualne.
- Kliknij Rozpocznij
obok nowego urządzenia:
Po chwili otworzy się emulator.
Instrukcje dotyczące emulatora – aktualizacja Usług Google Play
- Po uruchomieniu emulatora kliknij … na pasku nawigacyjnym, który się pojawi**.**
Otworzy się okno Rozszerzone elementy sterujące.
- W menu kliknij Google Play.
Jeśli aktualizacja jest dostępna, kliknij Aktualizuj.
- Zaloguj się w emulatorze za pomocą konta Google.
Możesz użyć własnego konta lub utworzyć nowe bezpłatne konto, aby oddzielić testy od informacji osobistych.
Otworzy się Sklep Google Play z Usługami Google Play.
- Kliknij Aktualizuj, aby pobrać najnowszą wersję Usług Google Play.
Jeśli pojawi się prośba o dokończenie konfigurowania konta i dodanie opcji płatności, kliknij Pomiń.
Ustawianie lokalizacji w emulatorze
- Po uruchomieniu emulatora wpisz „mapy” na pasku wyszukiwania na ekranie głównym, aby wyświetlić ikonę aplikacji Mapy Google.
- Kliknij ikonę, aby uruchomić aplikację.
Zobaczysz domyślną mapę.
- W prawym dolnym rogu mapy kliknij Twoja lokalizacja
.
Pojawi się prośba o przyznanie telefonowi uprawnień do korzystania z lokalizacji.
- Kliknij …, aby otworzyć menu Rozszerzone opcje.
- Kliknij kartę Lokalizacja.
- Wpisz szerokość i długość geograficzną.
Wpisz dowolne miejsce, ale upewnij się, że w jego pobliżu jest wiele innych miejsc.
(Aby odtworzyć wyniki z tego laboratorium, użyj szerokości geograficznej 20,7818 i długości geograficznej -156,4624 dla miasta Kihei na wyspie Maui na Hawajach).
- Kliknij Wyślij, a mapa zostanie zaktualizowana o tę lokalizację.
Możesz teraz uruchomić aplikację i przetestować ją z lokalizacją.
Instrukcje dotyczące prawdziwego urządzenia – aktualizacja Usług Google Play
Jeśli używasz prawdziwego urządzenia z Androidem, wykonaj te czynności:
- Na pasku wyszukiwania na ekranie głównym wyszukaj i otwórz Usługi Google Play.
- Kliknij Więcej szczegółów.
Jeśli jest dostępna, kliknij Aktualizuj.
4. Tworzenie szkieletu aplikacji z aktywnością Map Google
- Na ekranie powitalnym Android Studio kliknij Start a new Android Studio project (Rozpocznij nowy projekt w Android Studio).
- Na karcie Telefon i tablet wybierz Aktywność w Mapach Google.
Otworzy się okno Skonfiguruj projekt. W tym miejscu możesz nazwać aplikację i utworzyć pakiet na podstawie domeny.
Oto ustawienia aplikacji o nazwie Current Place, która odpowiada pakietowi com.google.codelab.currentplace
.
- Wybierz język Java i kliknij Use androidx. artifacts* (Użyj artefaktów androidx).
W pozostałych ustawieniach zachowaj wartości domyślne.
- Kliknij Zakończ.
5. Dodawanie zależności Usług Google do pliku kompilacji Gradle
Aby uzyskać dostęp do uprawnień związanych z lokalizacją na urządzeniach z Androidem, musisz mieć interfejs Google Location and Activity Recognition API z Usług Google Play. Więcej informacji o dodawaniu tego i innych interfejsów API Usług Google Play znajdziesz w artykule Konfigurowanie Usług Google Play.
Projekty Android Studio mają zwykle 2 pliki build.gradle
. Jeden dotyczy całego projektu, a drugi – aplikacji. Jeśli w Android Studio masz otwarty eksplorator projektu w widoku Android, oba pliki zobaczysz w folderze Gradle Scripts
. Aby dodać usługi Google, musisz edytować plik build.gradle (Module: app)
.
- Dodaj 2 wiersze do sekcji
dependencies
, aby dodać usługi Google do określania lokalizacji i interfejs Places API ( przykładowy kod w kontekście).
build.gradle (Module: 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. Włączanie interfejsów API Google Maps Platform i uzyskiwanie klucza interfejsu API
Aby wykonać następny krok , musisz włączyć Maps SDK na Androida i Places API.
Konfigurowanie Google Maps Platform
Jeśli nie masz jeszcze konta Google Cloud Platform i projektu z włączonymi płatnościami, zapoznaj się z przewodnikiem Pierwsze kroki z Google Maps Platform, aby utworzyć konto rozliczeniowe i projekt.
- W konsoli Google Cloud kliknij menu projektu i wybierz projekt, którego chcesz użyć w tym samouczku.
- Włącz interfejsy API i pakiety SDK Google Maps Platform wymagane w tym samouczku w Google Cloud Marketplace. Aby to zrobić, wykonaj czynności opisane w tym filmie lub tej dokumentacji.
- Wygeneruj klucz interfejsu API na stronie Dane logowania w konsoli Cloud. Możesz wykonać czynności opisane w tym filmie lub tej dokumentacji. Wszystkie żądania wysyłane do Google Maps Platform wymagają klucza interfejsu API.
Skopiuj utworzony klucz interfejsu API. Wróć do Android Studio i znajdź plik google_maps_api.xml
w sekcji Android > app > res > values.
Zastąp YOUR_KEY_HERE
skopiowanym kluczem interfejsu API.
Aplikacja została skonfigurowana.
7. Edytowanie pliku układu
- W eksploratorze projektu otwórz plik
activity_maps.xml
w folderze Android >app
>res
>layout
.
- Po prawej stronie ekranu otworzy się podstawowy interfejs z kartami u dołu, które umożliwiają wybór edytora projektu lub tekstu. Kliknij Tekst i zastąp całą zawartość pliku układu tym kodem:
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>
Interfejs użytkownika będzie wyglądać tak:
8. Konfigurowanie paska aplikacji
Aby dać użytkownikowi przycisk, który może kliknąć, gdy chce wybrać bieżące miejsce, dodaj pasek aplikacji z ikoną, która wyszukuje bieżące miejsce użytkownika i wyświetla pobliskie prawdopodobne miejsca. Będzie on wyglądał :
Na telefonie wyświetla się tylko ikona. Na tablecie z większą ilością miejsca tekst jest również uwzględniony.
Tworzenie ikony
- W eksploratorze projektu kliknij Android > app, a następnie kliknij prawym przyciskiem myszy folder res i wybierz New (Nowy) > Image Asset (Zasób obrazu).
Otworzy się Asset Studio.
- W menu Typ ikony kliknij Ikony paska działań i kart.
- Nazwij komponent
ic_geolocate
. - Jako typ zasobu wybierz Clip Art**.**
- Kliknij grafikę obok opcji Clip Art (Klipart).
Otworzy się okno Wybierz ikonę.
- Wybierz ikonę.
Za pomocą paska wyszukiwania możesz znaleźć ikony związane z Twoim zamiarem.
- Wyszukaj
location
i wybierz ikonę związaną z lokalizacją.
Ikona mojej lokalizacji jest taka sama jak w aplikacji Mapy Google, gdy użytkownik chce skierować aparat na swoją bieżącą lokalizację.
- Kliknij OK > Dalej > Zakończ i sprawdź, czy jest nowy folder o nazwie
drawable
, który zawiera nowe pliki ikon.
Dodawanie zasobów w postaci ciągów znaków
- W eksploratorze projektu kliknij Android > app > res > values i otwórz plik
strings.xml
. - Po
<string name="title_activity_maps">Map</string>
dodaj te wiersze:
strings.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>
Pierwszy wiersz jest używany na pasku aplikacji, gdy jest miejsce na umieszczenie etykiety tekstowej obok ikony. Pozostałe są używane w przypadku znaczników dodawanych do mapy.
Teraz kod w pliku wygląda tak:
<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>
Dodawanie paska aplikacji
- W eksploratorze projektu kliknij Android > app, a następnie kliknij prawym przyciskiem myszy folder
res
i wybierz Nowy > Katalog, aby utworzyć nowy podkatalog wapp/src/main/res
. - Nazwij katalog
menu
. - Kliknij prawym przyciskiem myszy folder
menu
i wybierz Nowy > Plik. - Nadaj plikowi nazwę
menu.xml
. - Wklej ten kod:
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>
Aktualizowanie stylu paska aplikacji
- W eksploratorze projektu rozwiń kolejno Android >
app
>res
>values
i otwórz plikstyles.xml
. - W tagu
<style>
zmień właściwość elementu nadrzędnego na"Theme.AppCompat.NoActionBar"
. - Zanotuj właściwość
name
, której użyjesz w następnym kroku.
styles.xml
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
Aktualizowanie motywu aplikacji w pliku AndroidManifest.xml
- Kliknij Android >
app
>manifests
i otwórz plikAndroidManifest.xml
. - Znajdź wiersz
android:theme
i zmień lub potwierdź wartość@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">
Możesz już zacząć pisać kod.
9. Inicjowanie aplikacji
- W eksploratorze projektu znajdź plik
MapsActivity.java
.
Znajduje się on w folderze odpowiadającym pakietowi utworzonemu w kroku 1.
- Otwórz plik, a zostanie wyświetlony edytor kodu Java.
Zaimportuj pakiet SDK Miejsc i inne zależności
Dodaj te wiersze na początku pliku MapsActivity.java
, zastępując istniejące instrukcje importu.
Obejmują one istniejące importy i dodają wiele innych używanych w kodzie w tym laboratorium.
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;
Aktualizowanie podpisu zajęć
Interfejs Places API używa komponentów AndroidX, aby zapewnić zgodność wsteczną, więc musisz zdefiniować go tak, aby rozszerzał AppCompatActivity
. Zastępuje rozszerzenie FragmentActivity
, które jest domyślnie zdefiniowane dla aktywności związanej z mapami.
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
Dodawanie zmiennych zajęć
Następnie zadeklaruj różne zmienne klasy używane w różnych metodach klasy. Obejmują one elementy interfejsu i kody stanu. Powinny się one znajdować tuż pod deklaracją zmiennej 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;
Zaktualizuj metodę onCreate
Musisz zaktualizować metodę onCreate
, aby obsługiwała uprawnienia użytkownika w czasie działania aplikacji w zakresie usług lokalizacyjnych, konfigurowała elementy interfejsu i tworzyła klienta interfejsu Places API.
Dodaj te wiersze kodu dotyczące paska narzędzi działania, konfiguracji widoków i klienta Places na końcu istniejącej metody onCreate()
.
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);
}
Dodawanie kodu menu paska aplikacji
Te 2 metody dodają menu paska aplikacji (z 1 elementem, ikoną Wybierz miejsce) i obsługują kliknięcie ikony przez użytkownika.
Skopiuj te 2 metody do pliku po metodzie onCreate
.
MapsActivity.java onCreateOptionsMenu() i 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);
}
}
Przetestuj
- W Android Studio kliknij Uruchom lub Menu Uruchom > Uruchom „aplikację”.
- Zobaczysz prośbę o wybranie miejsca wdrożenia. Na tej liście powinien się pojawić uruchomiony emulator. Wybierz go, a Android Studio wdroży aplikację w emulatorze.
Po chwili aplikacja się uruchomi. Wyświetli się mapa wyśrodkowana na Sydney w Australii z jednym przyciskiem i pustą listą miejsc.
Środek mapy nie przesuwa się do lokalizacji użytkownika, chyba że poprosisz o uprawnienia dostępu do lokalizacji urządzenia.
10. Wysyłanie prośby o dostęp do lokalizacji i obsługa tego dostępu
Wysyłanie prośby o dostęp do lokalizacji po przygotowaniu mapy
- Zdefiniuj metodę o nazwie
getLocationPermission
, która prosi użytkownika o uprawnienia.
Wklej ten kod pod utworzoną przed chwilą metodą onOptionsSelected
.
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);
}
}
- Dodaj 2 wiersze na końcu istniejącej metody
onMapReady
, aby włączyć elementy sterujące powiększeniem i poprosić użytkownika o uprawnienia do lokalizacji.
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();
}
Obsługa wyniku prośby o uprawnienia
Gdy użytkownik odpowie na okno z prośbą o przyznanie uprawnień, Android wywoła to wywołanie zwrotne.
Wklej ten kod po metodzie 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. Pobieranie bieżącej lokalizacji i pobieranie prawdopodobnych miejsc
Gdy użytkownik kliknie Wybierz miejsce na pasku aplikacji, aplikacja wywoła metodę pickCurrentPlace()
, która wywoła zdefiniowaną wcześniej metodę getDeviceLocation()
. Metoda getDeviceLocation
wywołuje inną metodę, getCurrentPlaceLikelihoods,
, po pobraniu najnowszej lokalizacji urządzenia.
Wywołaj interfejs API findCurrentPlace i obsłuż odpowiedź
getCurrentPlaceLikelihoods
tworzy findCurrentPlaceRequest
i wywołuje zadanie Places API findCurrentPlace
. Jeśli zadanie się powiedzie, zwraca obiekt findCurrentPlaceResponse
, który zawiera listę obiektów placeLikelihood
. Każda z nich ma wiele właściwości, w tym nazwę i adres miejsca oraz prawdopodobieństwo, że się w nim znajdujesz (wartość zmiennoprzecinkowa od 0 do 1). Ta metoda obsługuje odpowiedź, tworząc listy szczegółów miejsca z placeLikelihoods
.
Ten kod iteruje po 5 najbardziej prawdopodobnych miejscach i dodaje do listy te, których prawdopodobieństwo jest większe niż 0. Następnie renderuje tę listę. Jeśli chcesz wyświetlać więcej lub mniej niż 5 elementów, zmień stałą M_MAX_ENTRIES
.
Wklej ten kod po metodzie 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());
}
}
}
});
}
Przesuwanie kamery mapy do bieżącej lokalizacji urządzenia
Jeśli użytkownik przyzna uprawnienia, aplikacja pobierze jego najnowszą lokalizację i wyśrodkuje na niej widok kamery.
Jeśli użytkownik odmówi przyznania uprawnień, aplikacja po prostu przeniesie kamerę do domyślnej lokalizacji zdefiniowanej wśród stałych wartości na początku tej strony (w przykładowym kodzie jest to Sydney w Australii).
Wklej ten kod po metodzie 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());
}
}
Sprawdzanie uprawnień do lokalizacji, gdy użytkownik kliknie Wybierz miejsce
Gdy użytkownik kliknie Wybierz miejsce, ta metoda sprawdza uprawnienia do lokalizacji i wyświetla prośbę o przyznanie uprawnień, jeśli nie zostały one jeszcze przyznane.
Jeśli użytkownik przyznał uprawnienia, metoda wywołuje funkcję getDeviceLocation
, aby rozpocząć proces pobierania bieżących prawdopodobnych miejsc.
- Dodaj tę metodę po
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();
}
}
- Teraz, gdy zdefiniowano
pickCurrentPlace
, znajdź wonOptionsItemSelected()
wiersz, który wywołujepickCurrentPlace
, i usuń z niego znacznik komentarza.
MapsActivity.java onOptionItemSelected()
case R.id.action_geolocate:
// COMMENTED OUT UNTIL WE DEFINE THE METHOD
// Present the Current Place picker
pickCurrentPlace();
return true;
Przetestuj
Jeśli teraz uruchomisz aplikację i klikniesz Wybierz miejsce, powinna ona poprosić o uprawnienia do lokalizacji.
- Jeśli zezwolisz na dostęp, preferencja zostanie zapisana i nie pojawi się prośba o zezwolenie. Jeśli odmówisz, przy następnym kliknięciu przycisku pojawi się prośba o przyznanie uprawnień.
- Chociaż
getPlaceLikelihoods
pobrał prawdopodobne bieżące miejsca,ListView
jeszcze ich nie wyświetla. W Android Studio możesz kliknąć ⌘6, aby sprawdzić logi w Logcat pod kątem instrukcji oznaczonych tagiem MapsActivity i upewnić się, że nowe metody działają prawidłowo. - Jeśli udzielisz uprawnień, dzienniki będą zawierać oświadczenie dotyczące
Latitude:
i oświadczenie dotycząceLongitude:
, w których będzie widoczna wykryta lokalizacja urządzenia. Jeśli wcześniej w Mapach Google i w rozszerzonym menu emulatora określono lokalizację emulatora, te instrukcje będą ją wyświetlać. - Jeśli wywołanie funkcji
findCurrentPlace
się powiedzie, dzienniki będą zawierać 5 instrukcji wyświetlających nazwy i lokalizacje 5 najbardziej prawdopodobnych miejsc.
12. Wypełnianie selektora Aktualne miejsce
Konfigurowanie funkcji obsługi wybranych miejsc
Zastanówmy się, co ma się stać, gdy użytkownik kliknie element w ListView
. Aby potwierdzić wybór użytkownika dotyczący miejsca, w którym się obecnie znajduje, możesz dodać do mapy znacznik w tym miejscu. Jeśli użytkownik kliknie ten znacznik, pojawi się okno informacyjne z nazwą i adresem miejsca.
Wklej ten moduł obsługi kliknięć po metodzie 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));
}
};
Wypełnianie widoku listy
Teraz, gdy masz już listę najbardziej prawdopodobnych miejsc, w których użytkownik obecnie przebywa, możesz wyświetlić te opcje w ListView
. Możesz też ustawić ListView
detektor kliknięć, aby używał zdefiniowanego przed chwilą modułu obsługi kliknięć.
Wklej tę metodę po funkcji obsługi kliknięć:
MapsActivity.java fillPlacesList()
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);
}
Teraz, gdy zdefiniowano fillPlacesList
, znajdź wiersz pod koniec findPlaceLikelihoods
, który wywołuje fillPlacesList
, i usuń z niego znacznik komentarza.
MapsActivity.java fillPlaceLikelihoods()
// COMMENTED OUT UNTIL WE DEFINE THE METHOD
// Populate the ListView
fillPlacesList();
To cały kod potrzebny do selektora bieżącego miejsca.
13. Uruchamianie aplikacji
Testowanie wyboru miejsca
- Uruchom ponownie aplikację.
Gdy tym razem klikniesz Wybierz miejsce, aplikacja wypełni listę nazwami miejsc w pobliżu. W pobliżu tego miejsca na Maui znajdują się m.in. Ululani's Hawaiian Shave Ice i Sugar Beach Bake Shop. Ponieważ kilka miejsc znajduje się bardzo blisko współrzędnych lokalizacji, jest to lista prawdopodobnych miejsc, w których możesz się znajdować.
- Kliknij nazwę miejsca w
ListView
.
Na mapie powinien pojawić się znacznik.
- Kliknij znacznik.
Możesz wyświetlić informacje o miejscu.
Sprawdź inną lokalizację
Jeśli chcesz zmienić lokalizację i korzystasz z emulatora, lokalizacja urządzenia nie zaktualizuje się automatycznie po zaktualizowaniu współrzędnych lokalizacji w menu rozszerzonym emulatora.
Aby to obejść, wykonaj te czynności, aby użyć natywnej aplikacji Mapy Google do wymuszenia aktualizacji lokalizacji emulatora:
- Otwórz Mapy Google.
- Kliknij … > Lokalizacja, aby zmienić szerokość i długość geograficzną na nowe współrzędne, a następnie kliknij Wyślij.
- Możesz na przykład użyć szerokości geograficznej 49.2768 i długości geograficznej -123.1142, aby ustawić lokalizację w centrum Vancouver w Kanadzie.
- Sprawdź, czy Mapy Google ponownie wyśrodkowały się na nowych współrzędnych. Aby poprosić o wyśrodkowanie, może być konieczne kliknięcie przycisku Moja lokalizacja w aplikacji Mapy Google.
- Wróć do aplikacji Current Place i kliknij Pick Place (Wybierz miejsce), aby wyświetlić mapę z nowymi współrzędnymi i nową listę prawdopodobnych bieżących lokalizacji.
To wszystko. Masz prostą aplikację, która sprawdza miejsca w bieżącej lokalizacji i określa prawdopodobieństwo, że w nich jesteś. Miłej zabawy!
Teraz uruchom aplikację ze wprowadzonymi zmianami, aby wykonać ten dodatkowy krok.
14. Dalsze kroki
Aby zapobiec kradzieży klucza interfejsu API, musisz go zabezpieczyć, aby tylko Twoja aplikacja na Androida mogła go używać. Jeśli nie ograniczysz klucza, każda osoba, która go ma, może używać go do wywoływania interfejsów API Google Maps Platform, co spowoduje naliczenie opłat.
Uzyskiwanie certyfikatu SHA-1
Będzie Ci on potrzebny później, gdy będziesz ograniczać klucze interfejsu API. Poniżej znajdziesz instrukcje uzyskiwania certyfikatu debugowania.
W systemie Linux lub macOS otwórz okno terminala i wpisz:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
W przypadku systemów Windows Vista i Windows 7 uruchom to polecenie:
keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
Dane wyjściowe powinny być podobne do tych:
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
Wiersz zaczynający się od SHA1 zawiera odcisk cyfrowy SHA-1 certyfikatu. Odcisk palca to ciąg 20 dwucyfrowych liczb szesnastkowych oddzielonych dwukropkami.
Gdy aplikacja będzie gotowa do opublikowania, postępuj zgodnie z instrukcjami w tej dokumentacji, aby pobrać certyfikat wersji.
Dodawanie ograniczeń do klucza interfejsu API
- W konsoli Cloud kliknij Interfejsy API i usługi > Dane logowania.
Klucz użyty w tej aplikacji powinien być widoczny w sekcji Klucze interfejsu API.
- Kliknij
, aby edytować ustawienia klucza.
- Na stronie klucza interfejsu API w sekcji Ograniczenia klucza ustaw Ograniczenia aplikacji, wykonując te czynności:
- Kliknij Aplikacje na Androida i postępuj zgodnie z instrukcjami.
- Kliknij Dodaj element.
- Wpisz nazwę pakietu i odcisk cyfrowy certyfikatu SHA-1 (uzyskany w poprzedniej sekcji).
Na przykład:
com.google.codelab.currentplace
BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75s
- Aby zapewnić dodatkową ochronę, ustaw ograniczenia interfejsów API, wykonując te czynności:
- W sekcji Ograniczenia interfejsów API wybierz Ogranicz klucz.
- Wybierz Maps SDK na Androida i Places API.
- Kliknij kolejno Gotowe i Zapisz.
15. Gratulacje
Utworzono prostą aplikację, która sprawdza najbardziej prawdopodobne miejsca w bieżącej lokalizacji i dodaje do mapy znacznik wybranego przez użytkownika miejsca.
Więcej informacji
- Aby przyspieszyć proces tworzenia, skorzystaj z biblioteki narzędziowej pakietu Maps SDK na Androida. Te narzędzia wykonują większość pracy związanej z najpopularniejszymi zadaniami w aplikacjach korzystających z Google Maps Platform.
- Więcej przykładowych fragmentów kodu demonstrujących większość funkcji pakietów Google Maps Platform SDK na Androida znajdziesz w sklonowanych repozytoriach przykładowych fragmentów kodu pakietu Maps SDK na Androida i prezentacji pakietu Places SDK na Androida.
- Aby dowiedzieć się, jak obsługiwać trójstanowe uprawnienia do lokalizacji w Androidzie Q, wykonaj ćwiczenie (w Codelabs) Otrzymywanie aktualizacji lokalizacji w Androidzie za pomocą języka Kotlin.