Hãy sử dụng hướng dẫn này để cho phép ứng dụng của bạn nghe và phản hồi nhiều sự kiện thay đổi khi người dùng di chuyển dọc theo một tuyến đường. Hướng dẫn này không đề cập đến việc xác định tuyến đường, chỉ phản hồi các sự kiện dọc theo tuyến đường.
Tổng quan
SDK Điều hướng cho iOS cung cấp cho bạn trình nghe liên kết với vị trí của người dùng và các điều kiện dọc theo tuyến đường, cũng như dữ liệu quan trọng về thời gian và khoảng cách. Trên trình điều khiển thành phần hiển thị của bản đồ, ứng dụng của bạn cần sử dụng các giao thức cho các trình nghe này: GMSRoadSnappedLocationProviderListener
và GMSNavigatorListener
.
Danh sách này cho thấy các phương thức trình nghe có sẵn cho sự kiện điều hướng:
GMSNavigatorListener.didArriveAtWaypoint
, được kích hoạt khi đạt đến một đích đến.GMSNavigatorListener.navigatorDidChangeRoute
, được kích hoạt khi tuyến thay đổi.GMSNavigatorListener.didUpdateRemainingTime
, được gọi nhiều lần khi thời gian đến đích tiếp theo thay đổi, trong khi hướng dẫn đang hoạt động.GMSNavigatorListener.didUpdateRemainingDistance
, được gọi nhiều lần khi khoảng cách đến đích đến tiếp theo thay đổi, trong khi tính năng chỉ đường đang hoạt động.GMSNavigatorListener.didUpdateDelayCategory
, được gọi khi danh mục độ trễ đến đích tiếp theo thay đổi, trong khi hướng dẫn đang hoạt động.GMSNavigatorListener.didChangeSuggestedLightingMode
, được kích hoạt khi điều kiện ánh sáng ước tính được cập nhật. Ví dụ: khi trời tối ở vị trí hiện tại của người dùng, ánh sáng sẽ thay đổi.GMSNavigatorListener.didUpdateSpeedingPercentage
, được kích hoạt khi người lái xe vượt quá giới hạn tốc độ.GMSRoadSnappedLocationProviderListener.didUpdateLocation
, được gọi nhiều lần khi vị trí của người dùng thay đổi.
Xem mã
Hiện/Ẩn mã Swift cho trình nghe sự kiện.
/* * 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) } }
Hiển thị/Ẩn mã Objective-C cho trình nghe sự kiện.
/* * 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
Khai báo việc tuân thủ các giao thức bắt buộc
Trước khi triển khai các phương thức điều hướng, trình điều khiển thành phần hiển thị phải sử dụng các giao thức sau:
class ViewController: UIViewController, GMSNavigatorListener,
GMSRoadSnappedLocationProviderListener {
@interface ViewController () <GMSNavigatorListener,
GMSRoadSnappedLocationProviderListener>
@end
Sau khi áp dụng các giao thức điều hướng, hãy đặt trình nghe thành trình điều khiển chế độ xem. Ví dụ: bạn có thể thêm mã sau vào phương thức viewDidLoad()
.
mapView.navigator?.add(self) mapView.roadSnappedLocationProvider?.add(self)
[_mapView.navigator addListener:self]; [_mapView.roadSnappedLocationProvider
addListener:self];
Nhận hoặc dừng thông tin cập nhật vị trí
Bạn cần cập nhật thông tin vị trí để hiển thị tiến trình của người dùng trên bản đồ.
Phiên bản location
hiển thị các thuộc tính sau:
Thuộc tính vị trí | Mô tả |
---|---|
độ cao | Độ cao hiện tại. |
coordinate.latitude | Toạ độ theo vĩ độ hiện tại được chụp nhanh trên đường. |
coordinate.longitude | Toạ độ kinh độ hiện tại được chụp nhanh trên đường. |
khoá học | Góc phương vị hiện tại tính bằng độ. |
tốc độ | Tốc độ hiện tại. |
dấu thời gian | Ngày/giờ của chỉ số hiện tại. |
Để nhận thông tin cập nhật liên tục về vị trí, hãy gọi mapView.roadSnappedLocationProvider.startUpdatingLocation
và sử dụng GMSRoadSnappedLocationProviderListener
để xử lý sự kiện didUpdateLocation
.
Ví dụ sau đây cho thấy cách gọi startUpdatingLocation
:
mapView.roadSnappedLocationProvider.startUpdatingLocation()
[_mapView.roadSnappedLocationProvider startUpdatingLocation];
Mã sau đây tạo một GMSRoadSnappedLocationProviderListener
để xử lý sự kiện didUpdateLocation
.
func locationProvider(_ locationProvider: GMSRoadSnappedLocationProvider,
didUpdate location: CLLocation) { print("Location: \(location.description)") }
- (void)locationProvider:(GMSRoadSnappedLocationProvider *)locationProvider
didUpdateLocation:(CLLocation *)location { NSLog(@"Location: %@",
location.description); }
Để nhận thông tin cập nhật về vị trí khi ứng dụng chạy ở chế độ nền, hãy đặt allowsBackgroundLocationUpdates
thành true:
mapView.roadSnappedLocationProvider.allowsBackgroundLocationUpdates = true
_mapView.roadSnappedLocationProvider.allowsBackgroundLocationUpdates = YES;
Phát hiện sự kiện đến
Ứng dụng của bạn sử dụng sự kiện didArriveAtWaypoint
để phát hiện thời điểm đạt đến một đích đến. Bạn có thể tiếp tục chỉ dẫn và chuyển đến điểm trung gian tiếp theo bằng cách gọi continueToNextDestination()
, sau đó bật lại chỉ dẫn. Ứng dụng của bạn phải bật lại hướng dẫn sau khi gọi continueToNextDestination()
.
Sau khi ứng dụng gọi continueToNextDestination
, trình điều hướng sẽ không còn dữ liệu về đích đến trước đó nữa. Nếu muốn phân tích thông tin về một chặng đường, bạn phải truy xuất thông tin này từ trình điều hướng trước khi gọi continueToNextDestination()
.
Ví dụ về mã sau đây cho thấy một phương thức để xử lý sự kiện 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; }
Nhận thông tin cập nhật về thay đổi tuyến đường
Để nhận thông báo mỗi khi tuyến thay đổi, hãy tạo một phương thức để xử lý sự kiện navigatorDidChangeRoute
. Bạn có thể truy cập vào tuyến mới bằng cách sử dụng các thuộc tính routeLegs
và currentRouteLeg
của GMSNavigator
.
func navigatorDidChangeRoute(_ navigator: GMSNavigator) { print("The route has
changed.") }
- (void)navigatorDidChangeRoute:(GMSNavigator *)navigator { NSLog(@"The route
has changed."); }
Nhận thông tin cập nhật về thời gian đến đích
Để nhận thông tin cập nhật liên tục về thời gian đến đích, hãy tạo một phương thức để xử lý sự kiện didUpdateRemainingTime
. Tham số time
cung cấp thời gian dự kiến, tính bằng giây, cho đến khi đến đích tiếp theo.
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); }
Để đặt mức thay đổi tối thiểu về thời gian dự kiến đến đích tiếp theo, hãy đặt thuộc tính timeUpdateThreshold
trên GMSNavigator
. Giá trị được chỉ định bằng giây. Nếu bạn không đặt thuộc tính này, các dịch vụ sẽ sử dụng giá trị mặc định là một giây.
navigator?.timeUpdateThreshold = 10
navigator.timeUpdateThreshold = 10;
Nhận thông tin cập nhật về khoảng cách đến đích
Để nhận thông tin cập nhật liên tục về khoảng cách đến đích, hãy tạo một phương thức để xử lý sự kiện didUpdateRemainingDistance
. Tham số distance
cung cấp quãng đường ước tính (tính bằng mét) đến đích tiếp theo.
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]); }
Để đặt mức thay đổi tối thiểu trong khoảng cách ước tính đến đích tiếp theo, hãy đặt thuộc tính distanceUpdateThreshold
trên GMSNavigator
(giá trị được chỉ định bằng mét). Nếu bạn không đặt thuộc tính này, các dịch vụ sẽ sử dụng giá trị mặc định là 1 mét.
navigator?.distanceUpdateThreshold = 100
navigator.distanceUpdateThreshold = 100;
Nhận thông tin cập nhật về lưu lượng truy cập
Để nhận thông tin cập nhật liên tục về luồng giao thông cho tuyến còn lại, hãy tạo một phương thức để xử lý sự kiện didUpdateDelayCategory
. Lệnh gọi đến delayCategoryToNextDestination
sẽ trả về GMSNavigationDelayCategory
, cung cấp giá trị từ 0 đến 3. Nội dung cập nhật cho danh mục dựa trên vị trí hiện tại của người dùng ứng dụng. Nếu không có dữ liệu lưu lượng truy cập, GMSNavigationDelayCategory
sẽ trả về 0. Các con số từ 1 đến 3 cho biết lưu lượng tăng dần từ ít đến nhiều.
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); }
Thuộc tính GMSNavigationDelayCategory
hiển thị các mức độ trễ sau:
Danh mục độ trễ | Mô tả |
---|---|
GMSNavigationDelayCategoryNoData | 0 – Không có sẵn, không có dữ liệu về lưu lượng truy cập hoặc : |
tuyến đường. | |
GMSNavigationDelayCategoryHeavy | 1 – Nặng. |
GMSNavigationDelayCategoryMedium | 2 – Trung bình. |
GMSNavigationDelayCategoryLight | 3 – Ánh sáng. |
Nhận thông tin cập nhật về tốc độ
Để nhận thông tin cập nhật khi người lái xe vượt quá giới hạn tốc độ, hãy tạo một phương thức để xử lý sự kiện 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); }
Thay đổi chế độ chiếu sáng được đề xuất
Để nhận thông tin cập nhật về những thay đổi ước tính về ánh sáng, hãy tạo một phương thức để xử lý sự kiện 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; }