Tạo kiểu bản đồ mới sắp xuất hiện trên Nền tảng Google Maps. Bản cập nhật này để tạo kiểu bản đồ bao gồm một bảng màu mặc định mới và các cải tiến về trải nghiệm bản đồ cũng như khả năng hữu dụng. Tất cả kiểu bản đồ sẽ được cập nhật tự động vào tháng 3 năm 2025. Để biết thêm thông tin về phạm vi cung cấp và cách chọn tham gia sớm hơn, hãy xem bài viết Kiểu bản đồ mới cho Nền tảng Google Maps.
Hãy sử dụng hướng dẫn này để cho phép ứng dụng của bạn theo dõi và phản hồi nhiều sự kiện thay đổi khi người dùng di chuyển trong một tuyến đường. Hướng dẫn này không đề cập đến việc xác định một tuyến mà chỉ phản hồi các sự kiện trên một tuyến đường đó.
Tổng quan
SDK Điều hướng dành cho iOS cung cấp cho bạn các trình nghe liên quan đến vị trí của người dùng và các điều kiện trên 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 kiểm soát chế độ xem của bản đồ, ứng dụng của bạn cần áp dụng các giao thức cho các trình nghe này: GMSRoadSnappedLocationProviderListener và GMSNavigatorListener.
Danh sách này cho biết các phương thức của trình nghe có sẵn cho sự kiện điều hướng:
/*
* 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/ẩ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 sự 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, bộ điều khiển chế độ xem phải sử dụng các giao thức:
Sau khi áp dụng các giao thức điều hướng, hãy đặt trình nghe thành bộ điều khiển chế độ xem. Ví dụ: bạn có thể thêm mã sau vào phương thức viewDidLoad().
Cần có thông tin cập nhật vị trí để hiển thị tiến trình của người dùng trên bản đồ.
Thực thể location cho thấy các thuộc tính sau:
Thuộc tính vị trí
Nội dung mô tả
độ cao
Độ cao hiện tại.
coordinate.latitude
Toạ độ theo vĩ độ hiện tại theo đường chụp.
coordinate.longitude
Toạ độ kinh độ bị chụp đường hiện tại.
khoá học
Góc hiện tại tính theo độ.
tốc độ
Tốc độ hiện tại.
timestamp
Ngày/giờ của chỉ số hiện tại.
Để liên tục nhận được thông tin cập nhật 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:
Ứng dụng của bạn sử dụng sự kiện didArriveAtWaypoint để phát hiện thời điểm người dùng đã đến một đích đến. Bạn có thể tiếp tục hướng dẫn và chuyển đến điểm tham chiếu tiếp theo bằng cách gọi continueToNextDestination(), sau đó bật lại hướng 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 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ề chân tuyến đường, bạn phải truy xuất chân này từ trình điều hướng trước khi gọi continueToNextDestination().
Mã ví dụ sau đây cho thấy một phương thức để xử lý sự kiện didArriveAtWaypoint:
(void)navigation:(GMSNavigator *)navigator
didĐIAtwaypoint:(GMSNavigationwaypoint *)waypoint { NSLog(@"Bạn đã
đến lúc: %@", Waypoint.title); [_mapView.navigation.navigator
continueToNextDestination]; _mapView.navigator.GuideanceActive = YES; }
Nhận thông tin cập nhật về thay đổi tuyến đường
Để nhận thông báo bất cứ khi nào tuyến đường này 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 tuyến mới bằng cách sử dụng các thuộc tính routeLegs và currentRouteLeg của GMSNavigator.
Swift
Func navigatorDidChangeRoute(_ navigation: GMSNavigator) { print("Tuyến đường đã thay đổi.") }
Objective-C
(void)navigatorDidChangeRoute:(GMSNavigator *)navigation { NSLog(@"Tuyến đường đã thay đổi."); }
Đang nhận thông tin cập nhật về thời gian tới điểm đến
Để nhận được thời gian liên tục tới thông tin cập nhật đích đến, 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 ước tính (tính bằng giây) cho đến khi đến đích đến tiếp theo.
Swift
Func navigation(_ trình điều hướng: GMSNavigator, DidUpdateRemainingTime:
TimeInterval) { print("Thời gian tới điểm đến tiếp theo: (time)") }
Objective-C
(void)navigation:(GMSNavigator *)Navigationnavigation
didUpdateRemainingTime:(NSTimeInterval)time { NSLog(@"Time to next
destination: %f", time); }
Để đặt mức thay đổi tối thiểu về thời gian ước tính cho điểm đến 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.
Swift
navigation?.timeUpdatethreshold = 10
Objective-C
navigator.timeUpdateThreshold = 10;
Đang nhận thông tin cập nhật về khoảng cách đến điểm đến
Để nhận được khoảng cách liên tục đến thông tin cập nhật đích đến, hãy tạo một phương thức để xử lý sự kiện didUpdateRemainingDistance. Tham số distance cung cấp khoảng cách ước tính (tính bằng mét) đến đích đến tiếp theo.
Swift
Func navigation(_ trình điều hướng: GMSNavigator, DidUpdateRemainingDistance: CLLocationDistance) { cho phép dặm = khoảng cách * 0,00062137 print("Khoảng cách tới điểm đến tiếp theo: (dặm) dặm.") }
Objective-C
(void)navigation:(GMSNavigatorNavigator *)Navigationnavigation
đi
Để đặt mức thay đổi tối thiểu về khoảng cách ước tính tới điểm đến 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à một mét.
Swift
navigator?.distanceUpdateThreshold = 100
Objective-C
navigator.distanceUpdateThreshold = 100;
Đang nhận thông tin cập nhật về giao thông
Để nhận thông tin cập nhật liên tục về luồng lưu lượng truy cập cho tuyến đường 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 trả về GMSNavigationDelayCategory cung cấp giá trị từ 0 đến 3. Các bản 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 truy cập tăng dần từ nhẹ đến nặng.
Swift
Func navigator(_ navigation: GMSNavigator, DidUpdate delayCategory:
GMSNavigationDelayCategory) { print("Luồng giao thông đến điểm đến tiếp theo:
(delayCategory)") }
Objective-C
(void)navigation:(GMSNavigator *)navigationnavigation
didUpdateDelayCategory:(GMSNavigationDelayCategory)delayCategory {
NSLog(@"Luồng lưu lượng đến điểm đến tiếp theo: %ld", (long)delayCategory); }
Thuộc tính GMSNavigationDelayCategory cho thấy các mức độ trễ sau:
Danh mục độ trễ
Nội dung mô tả
GMSNavigationDelayCategoryNoData
0 - Không có, không có dữ liệu cho giao thông hoặc :
tuyến đường.
GMSNavigationDelayCategoryHeavy
1 – Lớn.
GMSNavigationDelayCategoryMedium
2 – Trung bình.
GMSNavigationDelayCategoryLight
3 – Sáng.
Đang 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.
Swift
// Trình nghe để xử lý các sự kiện tăng tốc. navigation vui }
Objective-C
// Trình nghe để xử lý các sự kiện tăng tốc. – (void)navigator:(GMSNavigatorNavigator
*)navigator DidUpdateSpeedingPercentage:(CGFloat)percentageTopLimit {
NSLog(@"Speed is %f Sử dụng phần trăm vượt quá giới hạn.", tỷ Giá phần trăm; giới hạn); }
Thay đổi chế độ chiếu sáng được đề xuất
Để nhận thông tin cập nhật về các 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.
Swift
// Xác định trình nghe cho các thay đổi được đề xuất đối với chế độ chiếu sáng. Func navigation(_ navigation: GMSNavigator, DidChangeSuggestedLightingMode LightMode:
GMSNavigationLightingMode) { print("Gợi ý chế độ ánh sáng đã thay đổi:
(String(describing: lightMode))")
// Thực hiện thay đổi được đề xuất. mapView.lightingMode = lightMode }
Objective-C
// Xác định trình nghe cho các thay đổi được đề xuất đối với chế độ chiếu sáng.
-(void)navigator:(GMSNavigator *)Navgator DidChangeSuggestedLightingMode:
(GMSNavigationLightingMode)lightingMode { NSLog(@"Gợi ý chế độ chiếu sáng đã
thay đổi: %ld", (long)lightingMode);
// Thực hiện thay đổi được đề xuất. _mapView.lightingMode = sángMode; }