Utilizza questa guida per consentire alla tua app di ascoltare e rispondere a una serie di eventi che cambiano man mano che un utente si sposta lungo un percorso. Questa guida non riguarda la definizione di un percorso, ma solo la risposta agli eventi lungo un percorso.
Panoramica
L'SDK di navigazione per iOS fornisce ascoltatori associati alla posizione dell'utente e alle condizioni lungo il percorso, nonché dati importanti su tempo e distanza. Nel controller della visualizzazione della mappa, la tua app deve adottare i protocolli per questi ascoltatori:
GMSRoadSnappedLocationProviderListener
e
GMSNavigatorListener
.
Questo elenco mostra i metodi di listener disponibili per gli eventi di navigazione:
GMSNavigatorListener.didArriveAtWaypoint
, attivato quando viene raggiunta una destinazione.GMSNavigatorListener.navigatorDidChangeRoute
, attivato quando il percorso cambia.GMSNavigatorListener.didUpdateRemainingTime
, chiamato ripetutamente quando cambia il tempo per la destinazione successiva, mentre la guida è attiva.GMSNavigatorListener.didUpdateRemainingDistance
, chiamato ripetutamente man mano che la distanza dalla destinazione successiva cambia, mentre la guida è attiva.GMSNavigatorListener.didUpdateDelayCategory
, invocato quando cambia la categoria di ritardo per la destinazione successiva, mentre la guida è attiva.GMSNavigatorListener.didChangeSuggestedLightingMode
, attivato quando le condizioni di illuminazione stimate vengono aggiornate. Ad esempio, quando cala la notte nella posizione attuale dell'utente, l'illuminazione cambia.GMSNavigatorListener.didUpdateSpeedingPercentage
, attivato quando il conducente supera il limite di velocità.GMSRoadSnappedLocationProviderListener.didUpdateLocation
, chiamato ripetutamente man mano che la posizione dell'utente cambia.
Visualizza il codice
Mostra/Nascondi il codice Swift per un listener di eventi.
/* * 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) } }
Mostra/Nascondi il codice Objective-C per un listener di eventi.
/* * 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
Dichiarazione di conformità ai protocolli richiesti
Prima di implementare i metodi di navigazione, il controller della vista deve adottare i protocolli:
class ViewController: UIViewController, GMSNavigatorListener,
GMSRoadSnappedLocationProviderListener {
@interface ViewController () <GMSNavigatorListener,
GMSRoadSnappedLocationProviderListener>
@end
Dopo aver adottato i protocolli di navigazione, imposta gli ascoltatori sul controller della vista. Ad esempio, puoi aggiungere il seguente codice al metodo viewDidLoad()
.
mapView.navigator?.add(self) mapView.roadSnappedLocationProvider?.add(self)
[_mapView.navigator addListener:self]; [_mapView.roadSnappedLocationProvider
addListener:self];
Ricevere o interrompere gli aggiornamenti sulla posizione
Gli aggiornamenti della posizione sono necessari per mostrare i progressi dell'utente sulla mappa.
L'istanza location
espone le seguenti proprietà:
Proprietà Location | Descrizione |
---|---|
altitudine | Altitudine attuale. |
coordinate.latitude | La coordinata di latitudine attuale basata sulla strada. |
coordinate.longitude | La coordinata della longitudine corrente basata sulla strada. |
corso | Orientamento attuale in gradi. |
velocità | Velocità attuale. |
timestamp | Data/ora della lettura corrente. |
Per ricevere aggiornamenti continui sulla posizione, chiama
mapView.roadSnappedLocationProvider.startUpdatingLocation
e utilizza
GMSRoadSnappedLocationProviderListener
per gestire l'evento didUpdateLocation
.
L'esempio seguente mostra la chiamata a startUpdatingLocation
:
mapView.roadSnappedLocationProvider.startUpdatingLocation()
[_mapView.roadSnappedLocationProvider startUpdatingLocation];
Il seguente codice crea un GMSRoadSnappedLocationProviderListener
che gestisce l'evento didUpdateLocation
.
func locationProvider(_ locationProvider: GMSRoadSnappedLocationProvider,
didUpdate location: CLLocation) { print("Location: \(location.description)") }
- (void)locationProvider:(GMSRoadSnappedLocationProvider *)locationProvider
didUpdateLocation:(CLLocation *)location { NSLog(@"Location: %@",
location.description); }
Per ricevere aggiornamenti sulla posizione quando l'app è in background, imposta
allowsBackgroundLocationUpdates
su true:
mapView.roadSnappedLocationProvider.allowsBackgroundLocationUpdates = true
_mapView.roadSnappedLocationProvider.allowsBackgroundLocationUpdates = YES;
Rilevamento di eventi di arrivo
L'app utilizza l'evento didArriveAtWaypoint
per rilevare quando viene raggiunta una destinazione. Puoi riprendere le indicazioni stradali e passare al waypoint successivo premendo continueToNextDestination()
e riattivando le indicazioni stradali. L'app deve riattivare le indicazioni dopo aver chiamato continueToNextDestination()
.
Dopo che l'app chiama continueToNextDestination
, il navigatore non ha più dati sulla destinazione precedente. Se vuoi analizzare le informazioni su un tratto di un percorso, devi recuperarle dal navigatore prima di chiamare continueToNextDestination()
.
Il seguente esempio di codice mostra un metodo per gestire l'evento didArriveAtWaypoint
:
func navigator(_ navigator: GMSNavigator, didArriveAt waypoint:
GMSNavigationWaypoint) { print("You have arrived at: \(waypoint.title)")
mapView.navigator?.continueToNextDestination()
mapView.navigator?.isGuidanceActive = true }
- (void)navigator:(GMSNavigator *)navigator
didArriveAtWaypoint:(GMSNavigationWaypoint *)waypoint { NSLog(@"You have
arrived at: %@", waypoint.title); [_mapView.navigator
continueToNextDestination]; _mapView.navigator.guidanceActive = YES; }
Ricevere aggiornamenti sulle modifiche al percorso
Per ricevere una notifica ogni volta che il percorso viene modificato, crea un metodo per gestire l'evento navigatorDidChangeRoute
. Puoi accedere al nuovo percorso utilizzando le proprietà routeLegs
e currentRouteLeg
di GMSNavigator
.
func navigatorDidChangeRoute(_ navigator: GMSNavigator) { print("The route has
changed.") }
- (void)navigatorDidChangeRoute:(GMSNavigator *)navigator { NSLog(@"The route
has changed."); }
Ricevere aggiornamenti sul tempo di arrivo alla destinazione
Per ricevere aggiornamenti continui sul tempo di arrivo alla destinazione, crea un metodo per gestire l'evento didUpdateRemainingTime
. Il parametro time
fornisce il tempo stimato, in secondi, fino al raggiungimento della destinazione successiva.
func navigator(_ navigator: GMSNavigator, didUpdateRemainingTime time:
TimeInterval) { print("Time to next destination: \(time)") }
- (void)navigator:(GMSNavigator *)navigator
didUpdateRemainingTime:(NSTimeInterval)time { NSLog(@"Time to next
destination: %f", time); }
Per impostare la variazione minima del tempo stimato per la destinazione successiva, imposta la proprietà
timeUpdateThreshold
su GMSNavigator
. Il valore è specificato in secondi. Se questa proprietà non è impostata, i servizi utilizzano un valore predefinito di un
secondo.
navigator?.timeUpdateThreshold = 10
navigator.timeUpdateThreshold = 10;
Ricevere aggiornamenti sulla distanza dalla destinazione
Per ricevere aggiornamenti continui sulla distanza dalla destinazione, crea un metodo per gestire
l'evento didUpdateRemainingDistance
. Il parametro distance
fornisce la distanza stimata, in metri, alla destinazione successiva.
func navigator(_ navigator: GMSNavigator, didUpdateRemainingDistance distance:
CLLocationDistance) { let miles = distance * 0.00062137 print("Distance to next
destination: \(miles) miles.") }
- (void)navigator:(GMSNavigator *)navigator
didUpdateRemainingDistance:(CLLocationDistance)distance { double miles =
distance * 0.00062137; NSLog(@"%@", [NSString stringWithFormat:@"Distance to
next destination: %.2f.", miles]); }
Per impostare la variazione minima della distanza stimata alla destinazione successiva, imposta la proprietà distanceUpdateThreshold
su GMSNavigator
(il valore è specificato in metri). Se questa proprietà non è impostata, i servizi utilizzano un valore predefinito di un
metro.
navigator?.distanceUpdateThreshold = 100
navigator.distanceUpdateThreshold = 100;
Ricevere aggiornamenti sul traffico
Per ricevere aggiornamenti continui sul flusso del traffico per il percorso rimanente,
crea un metodo per gestire l'evento didUpdateDelayCategory
. Una chiamata a
delayCategoryToNextDestination
restituisce GMSNavigationDelayCategory
che fornisce un valore da 0 a 3. Gli aggiornamenti della categoria si basano sulla posizione corrente dell'utente dell'app. Se i dati sul traffico non sono disponibili,
GMSNavigationDelayCategory
restituisce 0. I numeri da 1 a 3 indicano un aumento del flusso da leggero a intenso.
func navigator(_ navigator: GMSNavigator, didUpdate delayCategory:
GMSNavigationDelayCategory) { print("Traffic flow to next destination:
\(delayCategory)") }
- (void)navigator:(GMSNavigator *)navigator
didUpdateDelayCategory:(GMSNavigationDelayCategory)delayCategory {
NSLog(@"Traffic flow to next destination: %ld", (long)delayCategory); }
La proprietà GMSNavigationDelayCategory
espone i seguenti livelli di ritardo:
Categoria di ritardo | Descrizione |
---|---|
GMSNavigationDelayCategoryNoData | 0 - Non disponibile, nessun dato sul traffico o : |
l'itinerario. | |
GMSNavigationDelayCategoryHeavy | 1 - Intenso. |
GMSNavigationDelayCategoryMedium | 2 - Medio. |
GMSNavigationDelayCategoryLight | 3 - Luce. |
Ricevere aggiornamenti sulla velocità
Per ricevere aggiornamenti quando un conducente supera il limite di velocità, crea un metodo per gestire l'evento didUpdateSpeedingPercentage
.
// Listener to handle speeding events. func navigator( _ navigator:
GMSNavigator, didUpdateSpeedingPercentage percentageAboveLimit: CGFloat ) {
print("Speed is \(percentageAboveLimit) above the limit.") }
// Listener to handle speeding events. - (void)navigator:(GMSNavigator
*)navigator didUpdateSpeedingPercentage:(CGFloat)percentageAboveLimit {
NSLog(@"Speed is %f percent above the limit.", percentageAboveLimit); }
Modificare la modalità di illuminazione suggerita
Per ricevere aggiornamenti sulle variazioni stimate dell'illuminazione, crea un metodo per gestire
l'evento didChangeSuggestedLightingMode
.
// Define a listener for suggested changes to lighting mode. func navigator(_
navigator: GMSNavigator, didChangeSuggestedLightingMode lightingMode:
GMSNavigationLightingMode) { print("Suggested lighting mode has changed:
\(String(describing: lightingMode))")
// Make the suggested change. mapView.lightingMode = lightingMode }
// Define a listener for suggested changes to lighting mode.
-(void)navigator:(GMSNavigator *)navigator didChangeSuggestedLightingMode:
(GMSNavigationLightingMode)lightingMode { NSLog(@"Suggested lighting mode has
changed: %ld", (long)lightingMode);
// Make the suggested change. _mapView.lightingMode = lightingMode; }