Wkrótce w Google Maps Platform udostępnimy nowy styl mapy. Ta aktualizacja stylu mapy obejmuje nową domyślną paletę kolorów oraz ulepszenia ułatwiające obsługę i łatwość obsługi map. Wszystkie style mapy zostaną automatycznie zaktualizowane w marcu 2025 r. Więcej informacji o dostępności i sposobie włączania tej funkcji znajdziesz w artykule Nowy styl mapy w Google Maps Platform.
Ten przewodnik pozwoli Ci włączyć w aplikacji nasłuchiwanie różnych zdarzeń, które zmieniają się, gdy użytkownik porusza się po trasie, i reagowanie na nie. Nie opisujemy tu definiowania trasy, a jedynie odpowiadanie na zdarzenia na trasie.
Przegląd
Pakiet Navigation SDK na iOS udostępnia detektory powiązane z lokalizacją użytkownika i warunkami na trasie, a także ważne dane o czasie i dystansie. W kontrolerze widoku mapy aplikacja musi przyjąć protokoły dla tych detektorów: GMSRoadSnappedLocationProviderListener i GMSNavigatorListener.
Ta lista zawiera metody detektora dostępne w przypadku zdarzeń nawigacji:
/*
* Copyright 2020 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import GoogleNavigation
import UIKit
class ViewController: UIViewController,
GMSNavigatorListener,
GMSRoadSnappedLocationProviderListener
{
var mapView: GMSMapView!
var locationManager: CLLocationManager!
override func loadView() {
locationManager = CLLocationManager()
let camera = GMSCameraPosition.camera(withLatitude: 47.67, longitude: -122.20, zoom: 14)
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
// Add listeners for GMSNavigator and GMSRoadSnappedLocationProvider.
mapView.navigator?.add(self)
mapView.roadSnappedLocationProvider?.add(self)
// Set the time update threshold (seconds) and distance update threshold (meters).
mapView.navigator?.timeUpdateThreshold = 10
mapView.navigator?.distanceUpdateThreshold = 100
// Show the terms and conditions.
let companyName = "Ride Sharing Co."
GMSNavigationServices.showTermsAndConditionsDialogIfNeeded(
withCompanyName: companyName
) { termsAccepted in
if termsAccepted {
// Enable navigation if the user accepts the terms.
self.mapView.isNavigationEnabled = true
// Request authorization to use location services.
self.locationManager.requestAlwaysAuthorization()
// Request authorization for alert notifications which deliver guidance instructions
// in the background.
UNUserNotificationCenter.current().requestAuthorization(options: [.alert]) {
granted, error in
// Handle denied authorization to display notifications.
if !granted || error != nil {
print("Authorization to deliver notifications was rejected.")
}
}
} else {
// Handle the case when the user rejects the terms and conditions.
}
}
view = mapView
makeButton()
}
// Create a route and start guidance.
@objc func startNav() {
var destinations = [GMSNavigationWaypoint]()
destinations.append(
GMSNavigationWaypoint.init(
placeID: "ChIJnUYTpNASkFQR_gSty5kyoUk",
title: "PCC Natural Market")!)
destinations.append(
GMSNavigationWaypoint.init(
placeID: "ChIJJ326ROcSkFQRBfUzOL2DSbo",
title: "Marina Park")!)
mapView.navigator?.setDestinations(destinations) { routeStatus in
guard routeStatus == .OK else {
print("Handle route statuses that are not OK.")
return
}
self.mapView.navigator?.isGuidanceActive = true
self.mapView.cameraMode = .following
self.mapView.locationSimulator?.simulateLocationsAlongExistingRoute()
}
mapView.roadSnappedLocationProvider?.startUpdatingLocation()
}
// Listener to handle continuous location updates.
func locationProvider(
_ locationProvider: GMSRoadSnappedLocationProvider,
didUpdate location: CLLocation
) {
print("Location: \(location.description)")
}
// Listener to handle speeding events.
func navigator(
_ navigator: GMSNavigator, didUpdateSpeedingPercentage percentageAboveLimit: CGFloat
) {
print("Speed is \(percentageAboveLimit) above the limit.")
}
// Listener to handle arrival events.
func navigator(_ navigator: GMSNavigator, didArriveAt waypoint: GMSNavigationWaypoint) {
print("You have arrived at: \(waypoint.title)")
mapView.navigator?.continueToNextDestination()
mapView.navigator?.isGuidanceActive = true
}
// Listener for route change events.
func navigatorDidChangeRoute(_ navigator: GMSNavigator) {
print("The route has changed.")
}
// Listener for time to next destination.
func navigator(_ navigator: GMSNavigator, didUpdateRemainingTime time: TimeInterval) {
print("Time to next destination: \(time)")
}
// Delegate for distance to next destination.
func navigator(
_ navigator: GMSNavigator,
didUpdateRemainingDistance distance: CLLocationDistance
) {
let miles = distance * 0.00062137
print("Distance to next destination: \(miles) miles.")
}
// Delegate for traffic updates to next destination
func navigator(
_ navigator: GMSNavigator,
didUpdate delayCategory: GMSNavigationDelayCategory
) {
print("Delay category to next destination: \(String(describing: delayCategory)).")
}
// Delegate for suggested lighting mode changes.
func navigator(
_ navigator: GMSNavigator,
didChangeSuggestedLightingMode lightingMode: GMSNavigationLightingMode
) {
print("Suggested lighting mode has changed: \(String(describing: lightingMode))")
// Change to the suggested lighting mode.
mapView.lightingMode = lightingMode
}
// Add a button to the view.
func makeButton() {
// Start navigation.
let navButton = UIButton(frame: CGRect(x: 5, y: 150, width: 200, height: 35))
navButton.backgroundColor = .blue
navButton.alpha = 0.5
navButton.setTitle("Start navigation", for: .normal)
navButton.addTarget(self, action: #selector(startNav), for: .touchUpInside)
self.mapView.addSubview(navButton)
}
}
Pokaż/ukryj kod Objective-C dla detektora zdarzeń.
/*
* Copyright 2020 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "ViewController.h"
@import GoogleNavigation;
@interface ViewController () <GMSNavigatorListener, GMSRoadSnappedLocationProviderListener>
@end
@implementation ViewController {
GMSMapView *_mapView;
CLLocationManager *_locationManager;
}
- (void)loadView {
_locationManager = [[CLLocationManager alloc] init];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:47.67
longitude:-122.20
zoom:14];
_mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
// Add listeners for GMSNavigator and GMSRoadSnappedLocationProvider.
[_mapView.navigator addListener:self];
[_mapView.roadSnappedLocationProvider addListener:self];
// Set the time update threshold (seconds) and distance update threshold (meters).
_mapView.navigator.timeUpdateThreshold = 10;
_mapView.navigator.distanceUpdateThreshold = 100;
// Show the terms and conditions.
NSString *companyName = @"Ride Sharing Co.";
[GMSNavigationServices
showTermsAndConditionsDialogIfNeededWithCompanyName:companyName
callback:^(BOOL termsAccepted) {
if (termsAccepted) {
// Enable navigation if the user accepts the terms.
_mapView.navigationEnabled = YES;
// Request authorization to use location services.
[_locationManager requestAlwaysAuthorization];
} else {
// Handle the case when the user rejects the terms and conditions.
}
}];
self.view = _mapView;
[self makeButton];
}
// Create a route and initiate navigation.
- (void)startNav {
NSArray<GMSNavigationWaypoint *> *destinations =
@[[[GMSNavigationWaypoint alloc] initWithPlaceID:@"ChIJnUYTpNASkFQR_gSty5kyoUk"
title:@"PCC Natural Market"],
[[GMSNavigationWaypoint alloc] initWithPlaceID:@"ChIJJ326ROcSkFQRBfUzOL2DSbo"
title:@"Marina Park"]];
[_mapView.navigator setDestinations:destinations
callback:^(GMSRouteStatus routeStatus){
_mapView.navigator.guidanceActive = YES;
_mapView.navigator.sendsBackgroundNotifications = YES;
_mapView.cameraMode = GMSNavigationCameraModeFollowing;
[_mapView.locationSimulator simulateLocationsAlongExistingRoute];
}];
[_mapView.roadSnappedLocationProvider startUpdatingLocation];
}
#pragma mark - GMSNavigatorListener
// Listener for continuous location updates.
- (void)locationProvider:(GMSRoadSnappedLocationProvider *)locationProvider
didUpdateLocation:(CLLocation *)location {
NSLog(@"Location: %@", location.description);
}
// Listener to handle speeding events.
- (void)navigator:(GMSNavigator *)navigator
didUpdateSpeedingPercentage:(CGFloat)percentageAboveLimit {
NSLog(@"Speed is %f percent above the limit.", percentageAboveLimit);
}
// Listener to handle arrival events.
- (void)navigator:(GMSNavigator *)navigator didArriveAtWaypoint:(GMSNavigationWaypoint *)waypoint {
NSLog(@"You have arrived at: %@", waypoint.title);
[_mapView.navigator continueToNextDestination];
_mapView.navigator.guidanceActive = YES;
}
// Listener for route change events.
- (void)navigatorDidChangeRoute:(GMSNavigator *)navigator {
NSLog(@"The route has changed.");
}
// Listener for time to next destination.
- (void)navigator:(GMSNavigator *)navigator didUpdateRemainingTime:(NSTimeInterval)time {
NSLog(@"Time to next destination: %f", time);
}
// Listener for distance to next destination.
- (void)navigator:(GMSNavigator *)navigator
didUpdateRemainingDistance:(CLLocationDistance)distance {
double miles = distance * 0.00062137;
NSLog(@"%@", [NSString stringWithFormat:@"Distance to next destination: %.2f.", miles]);
}
// Listener for traffic updates for next destination
- (void)navigator:(GMSNavigator *)navigator
didUpdateDelayCategory:(GMSNavigationDelayCategory)delayCategory {
NSLog(@"Delay category to next destination: %ld.", delayCategory);
}
// Listener for suggested lighting mode changes.
-(void)navigator:(GMSNavigator *)navigator
didChangeSuggestedLightingMode:(GMSNavigationLightingMode)lightingMode {
NSLog(@"Suggested lighting mode has changed: %ld", (long)lightingMode);
// Change to the suggested lighting mode.
_mapView.lightingMode = lightingMode;
}
#pragma mark - Programmatic UI elements
// Add a button to the view.
- (void)makeButton {
// Start navigation.
UIButton *navButton = [UIButton buttonWithType:UIButtonTypeCustom];
[navButton addTarget:self
action:@selector(startNav)
forControlEvents:UIControlEventTouchUpInside];
[navButton setTitle:@"Navigate" forState:UIControlStateNormal];
[navButton setBackgroundColor:[UIColor blueColor]];
[navButton setAlpha:0.5];
navButton.frame = CGRectMake(5.0, 150.0, 100.0, 35.0);
[_mapView addSubview:navButton];
}
@end
Deklaracja zgodności z wymaganymi protokołami
Przed zaimplementowaniem metod nawigacyjnych kontroler widoku musi przyjąć protokoły:
Swift
class ViewController: UIViewController, GMSNavigatorListener,
GMSRoadSnappedLocationProviderListener {
Otrzymywanie lub zatrzymywanie aktualizacji lokalizacji
Aby wyświetlać na mapie postępy użytkownika, wymagana jest aktualizacja lokalizacji.
Instancja location udostępnia te właściwości:
Usługa lokalizacji
Opis
wysokość n.p.m.
Aktualna wysokość.
coordinate.latitude
Bieżąca współrzędna szerokości geograficznej nałożonej na drogę.
coordinate.longitude
Bieżąca współrzędna długości geograficznej nałożonej na drogę.
szkolenie
Obecne odchylenie w stopniach.
szybkość
Obecna prędkość.
sygnatura czasowa
Data i godzina bieżącego odczytu.
Aby otrzymywać ciągłe aktualizacje lokalizacji, wywołaj metodę mapView.roadSnappedLocationProvider.startUpdatingLocation i użyj metody GMSRoadSnappedLocationProviderListener do obsługi zdarzenia didUpdateLocation.
Oto przykład wywoływania funkcji startUpdatingLocation:
Aplikacja używa zdarzenia didArriveAtWaypoint do wykrywania, kiedy dotarło się miejsce docelowe. Aby wznowić nawigację i przejść do następnego punktu na trasie, wywołaj continueToNextDestination(), a następnie ponownie włącz wskazówki. Aplikacja musi ponownie włączyć wskazówki po wywołaniu funkcji continueToNextDestination().
Po wywołaniu przez aplikację funkcji continueToNextDestination nawigator nie będzie już mieć danych o poprzednim miejscu docelowym. Jeśli chcesz przeanalizować informacje o danym etapie trasy, musisz pobrać je z nawigatora przed wywołaniem funkcji continueToNextDestination().
Następujący przykładowy kod pokazuje metodę obsługi zdarzenia didArriveAtWaypoint:
Aby otrzymywać powiadomienia po każdej zmianie trasy, utwórz metodę obsługi zdarzenia navigatorDidChangeRoute. Aby uzyskać dostęp do nowej trasy, skorzystaj z właściwości routeLegs i currentRouteLeg obiektu GMSNavigator.
Swift
func navigator DidChangeRoute(_ navigator: GMSNavigator) { print("Trasa się zmieniła.") }
Objective-C
(void)navigator DidChangeRoute:(GMSNavigator *)navigator { NSLog(@"Trasa została zmieniona."); }
Czas otrzymywania aktualizacji miejsca docelowego
Aby otrzymywać aktualizacje na bieżąco do miejsca docelowego, utwórz metodę do obsługi zdarzenia didUpdateRemainingTime. Parametr time podaje szacowany czas (w sekundach) do osiągnięcia następnego miejsca docelowego.
Swift
func navigator(_ navigator: GMSNavigator, didUpdateLastTime time:
TimeInterval) { press("Czas do następnego miejsca docelowego: (czas)") }
Objective-C
(void)navigator:(GMSNavigator *)navigator
didUpdateDetailsTime:(NSTimeInterval)time { NSLog(@"Time to next destination: %f", time); }
Aby ustawić minimalną zmianę szacowanego czasu do następnego miejsca docelowego, ustaw właściwość timeUpdateThreshold na GMSNavigator. Wartość jest podawana w sekundach. Jeśli ta właściwość jest nieskonfigurowana, usługi używają wartości domyślnej wynoszącej 1 sekundę.
Swift
navigator?.timeUpdateThreshold = 10
Objective-C
navigator.timeUpdateThreshold = 10;
Odbieram aktualizacje o odległości do miejsca docelowego
Aby otrzymywać aktualizacje o stałej odległości do miejsca docelowego, utwórz metodę obsługi zdarzenia didUpdateRemainingDistance. Parametr distance podaje szacunkową odległość (w metrach) do następnego miejsca docelowego.
Swift
func navigator(_ navigator: GMSNavigator, didUpdateLastOdległość odległość:
CLLocationLocation) { let minutes = odległość * 0.00062137 press("Odległość do następnego miejsca docelowego: (mile) mile.") }
Objective-C
(void)navigator:(GMSNavigator *)navigator
didUpdateDetailsRange:(CLLocationLocation)distance { doublemile =
distance * 0.00062137; NSLog(@"%@", [NSString stringWithFormat:@"Odległość do
następnego miejsca docelowego: %.2f.", mile]); }
Aby ustawić minimalną zmianę szacowanej odległości do następnego miejsca docelowego, ustaw właściwość distanceUpdateThreshold na GMSNavigator (wartość jest podawana w metrach). Jeśli ta właściwość nie jest skonfigurowana, usługi używają wartości domyślnej 1 metra.
Swift
navigator?.distanceUpdateThreshold = 100
Objective-C
navigator.distanceUpdateThreshold = 100;
Otrzymywanie aktualnych informacji o natężeniu ruchu
Aby otrzymywać ciągłe aktualizacje przepływu ruchu na pozostałej trasie, utwórz metodę do obsługi zdarzenia didUpdateDelayCategory. Wywołanie delayCategoryToNextDestination zwraca wartość GMSNavigationDelayCategory, która podaje wartość od 0 do 3. Zmiany w kategorii zależą
od bieżącej pozycji użytkownika aplikacji. Jeśli dane o ruchu są niedostępne, GMSNavigationDelayCategory zwraca wartość 0. Liczby 1–3 wskazują na rosnący
przepływ ze lekkich do intensywnych.
Swift
func navigator(_ navigator: GMSNavigator, DidUpdate delayCategory:
GMSNawigacja OpóźnienieCategory) {print("Przepływ ruchu do następnego miejsca docelowego:
(delayCategory)") }
Objective-C
(void)navigator:(GMSNavigator *)navigator
didUpdateDurationCategory:(GMS Navigation OpóźnienieCategory)delayCategory {
NSLog(@"Przepływ ruchu do następnego miejsca docelowego: %ld", (long)delayCategory); }
Właściwość GMSNavigationDelayCategory ujawnia te poziomy opóźnienia:
Kategoria opóźnienia
Opis
GMSNavigationDelayCategoryNoData
0 – niedostępne, brak danych o ruchu lub :
trasę.
GMSNavigationDelayCategoryHeavy
1 – ciężki.
GMSNavigationDelayCategoryMedium
2 – Średni.
GMSNavigationDelayCategoryLight
3 – jasny.
Otrzymuję powiadomienia o przekroczeniu prędkości
Aby otrzymywać powiadomienia o przekroczeniu dozwolonej prędkości przez kierowcę, utwórz metodę obsługi zdarzenia didUpdateSpeedingPercentage.
Swift
// Detektor obsługujący zdarzenia związane z prędkością. func navigator( _ navigator:
GMSNavigator, didUpdateSpeedingPercentageAboveLimit: CGFloat ) {
print("Prędkość jest (percentageAboveLimit) powyżej limitu.") }
Objective-C
// Detektor do obsługi zdarzeń związanych z prędkością. - (void)navigator:(GMSNavigator
*)navigator didUpdateSpeedingPercentage:(CGFloat)percentageAboveLimit {
NSLog(@"Speed is %f percent over the limit.", percentageAboveLimit); }
Zmieniam sugerowany tryb oświetlenia
Aby otrzymywać powiadomienia o szacunkowych zmianach w oświetleniu, utwórz metodę obsługi zdarzenia didChangeSuggestedLightingMode.
Swift
// Zdefiniuj odbiornik sugerowanych zmian w trybie oświetlenia. func navigator(_
navigator: GMSNavigator, didChangeSubmitLightingMode EquipmentMode:
GMSnavigationLightingMode) { press("Proponowany tryb oświetlenia uległ zmianie:
(String(decribe: uwzględnioneMode))")