1. 准备工作
在此 Codelab 中,您将学习如何创建一个简单的 iOS 应用,该应用使用 Google Maps Platform Navigation SDK 导航到预配置的目的地。
完成后,您的应用将如下所示。
前提条件
- 具备使用 Swift 进行基本 iOS 应用开发的知识。
- 对 Google Maps SDK 的基本概念(例如创建以特定位置为中心的地图)有一定了解。
学习内容
- 如何创建一个简单的 iOS Swift 应用,该应用使用 Navigation SDK 导航到目的地。
- 如何从远程 Cocoapods 代码库集成 Navigation SDK。
- 如何管理位置信息权限以及 Navigation SDK 最终用户条款的用户同意书。
- 如何初始化 SDK。
- 如何设置目的地并启动导航指南。
所需条件
- 最新的稳定版 XCode。
- 启用了结算功能的 Google 账号和项目。
- 一台在 XCode 模拟器中运行的 iOS 设备或模拟设备。无论您选择哪种方法,都必须满足 Navigation SDK 的最低要求。
2. 进行设置
如果您还没有 Google Cloud Platform 账号和已启用结算功能的项目,请按照 Google Maps Platform 使用入门中的说明设置您的 Google Cloud 项目。
在控制台中选择一个 Google Cloud 项目
在 Cloud 控制台中,点击项目下拉菜单,然后选择要用于此 Codelab 的项目。
在项目中启用 Navigation SDK
在 Google Cloud Marketplace 中启用此 Codelab 所需的 Google Maps Platform API 和 SDK。
前往 API 和服务 >库,并搜索“Navigation SDK”。
您应该会看到一个搜索结果。
点击 Navigation SDK 以打开“商品详情”页面。点击启用,为您的项目启用该 SDK。
针对 Google Maps SDK for iOS 重复此过程。
创建 API 密钥
在 Cloud Console 的凭据页面中,生成 API 密钥。向 Google Maps Platform 发出的所有请求都需要 API 密钥。控制台中的“凭据”页面上。点击页面顶部的“+创建凭据”,然后从选项中选择“API 密钥”。
对于生产环境使用,最佳实践是为 API 密钥设置应用限制,但对于本 Codelab,这并非必需操作。
3. 获取示例项目文件
本部分介绍如何通过从此 Codelab 的 GitHub 代码库中克隆文件来设置基本的空 XCode 应用项目。GitHub 代码库包含此 Codelab 代码的前后版本。本 Codelab 将从空白项目模板开始,逐步构建到完成状态。如果您遇到问题,可以使用代码库中已完成的项目作为参考。
克隆代码库或下载代码
导航到您要存储此 Codelab 的目录。
然后克隆代码库或下载代码:
git clone https://github.com/googlemaps-samples/codelab-navigation-101-ios-swift
如果您未安装 git,请点击此按钮获取代码:
为帮助您尽快入门,代码库的 Starter
文件夹中包含一些起始代码,可帮助您顺利完成此 Codelab。此外,还有已完成的 Solution
项目,便于您随时继续或查看您的进度。要使用解决方案项目,您需要按照“使用 Cocoapods 安装”然后运行“Pod 更新”solution/Navigation SDK Codelab
文件夹中的命令。
在本地克隆代码库后,使用 XCode 将 Starter
文件夹作为现有项目打开。检查项目是否能构建和运行。
连接设备或设置 XCode 模拟器
4. 将 Navigation SDK 添加到您的应用
您可以通过三种方法将 Navigation SDK 集成到 XCode 项目中:此 Codelab 使用 CocoaPods。如需详细了解如何使用 Swift Package Manager 进行集成或通过下载 SDK 进行手动安装,请参阅 Navigation SDK 文档中的创建 Xcode 项目并安装 Navigation SDK。
使用 CocoaPods 安装
如果您还没有 CocoaPods 工具,请在 macOS 上从终端运行以下命令进行安装。如需了解详情,请参阅 CocoaPods 入门指南。
sudo gem install cocoapods
在 starter/Navigation SDK Codelab 文件夹内的项目文件夹中创建一个名为 Podfile 的新文件(在 XCode 中,依次点击 File > New > File > Other > Empty,另存为“Podfile”)
将以下内容添加到您的 Podfile
中:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '15.0'
target 'Navigation SDK Codelab' do
pod 'GoogleNavigation', '9.1.1'
end
可享受 Podfile
的优惠。
打开一个终端,并将目录切换到您保存 Podfile 的位置(这应该是 Codelab 代码库中的“starter/Navigation SDK Codelab”文件夹)
cd "<path-to-starter-project-folder>/Navigation SDK Codelab"
运行 pod install
命令。这会安装 Podfile
中指定的 API 以及所有依赖项
pod install
关闭 Xcode,然后打开项目的 .xcworkspace 文件以启动 Xcode。从此刻开始,您必须使用 .xcworkspace 文件打开项目。
检查是否已将 Pods 目录添加到项目结构中,以及该目录是否包含“GoogleMaps”和“GoogleNavigation”Pod。
添加您的 API 密钥
按照以下方法向 AppDelegate.swift
添加 API 密钥:
- 添加以下 import 语句:
import GoogleMaps
import GoogleNavigation
- 将以下代码添加到
application(_:didFinishLaunchingWithOptions:)
方法中:
GMSServices.provideAPIKey("YOUR_API_KEY")
将“YOUR_API_KEY”替换为您在上一步中创建的 API 密钥。
构建项目并修正所有错误。
5. 配置应用权限
Navigation SDK 依赖 GPS 信号来提供道路贴靠位置和精细导航,因此您的应用需要请求用户授予访问精确位置数据的权限。
为此,您需要在 Xcode 中向应用的 Info.plist 添加一些属性,向应用添加一些代码以在运行时向用户请求权限,并处理任何错误(例如未授予权限或位置信息不可用)。
在 Xcode 中打开 Info.plist。看上去应该类似这样
请求确切位置信息权限
您可以通过将鼠标指针悬停在“信息属性列表”上来添加新值。行,直到您看到“+”号图标。点击“+”即可看到一个包含建议的属性名称的对话框,但请注意,您也可以手动添加属性。
将以下属性和值添加到 Info.plist:
属性 | 值 |
“隐私 - 位置信息始终和使用时”使用情况说明 | “此应用需要获取您的设备位置信息,才能提供精细导航路线” |
隐私权 - 使用位置信息时的使用情况说明 | “此应用需要获取您的设备位置信息,才能提供精细导航路线” |
allowsBackgroundLocationUpdates | 是 |
请求后台位置信息权限
将以下属性和值添加到 Info.plist:
UIBackgroundModes
> 添加行 > Item 0: App registers for location updates
(从建议的下拉列表中选择此值)
完成后,Info.plist 应如下所示。
在运行时请求位置信息访问权限
将以下 import 语句添加到 ViewController.swift
:
import GoogleNavigation
将以下声明添加到 ViewController 类中:
var locationManager: CLLocationManager!
为 loadView()
添加方法替换项并调用 locationManager.requestAlwaysAuthorization()
:
override func loadView() {
locationManager = CLLocationManager()
locationManager.requestAlwaysAuthorization()
现在,您的应用程序将向用户请求位置信息,并在用户授予 权限后允许应用程序使用位置信息 。
请求显示通知的权限
将以下代码添加到 loadView() 中,以向用户请求显示通知的权限,这是显示导航操作说明所必需的。
UNUserNotificationCenter.current().requestAuthorization(options: [.alert]) {
granted, error in
// Handle denied authorization to display notifications.
if !granted || error != nil {
print("User rejected request to display notifications.")
}
}
构建并运行应用,检查系统是否提示您分享位置信息并启用通知。
6. 添加导航界面
在此步骤中,您将添加一张地图并将其配置为显示位置。然后,您将向用户显示一个包含 Navigation SDK 使用条款的对话框。
向应用添加地图视图
添加以下代码行,以在您的 ViewController 中声明 GMSMapView 变量。
var mapView: GMSMapView!
将以下代码添加到 Viewcontroller.swift
中的 loadView()
以初始化地图。
let camera = GMSCameraPosition.camera(withLatitude: 51.483174, longitude: -0.177369, zoom: 14)
let options = GMSMapViewOptions()
options.camera = camera
options.frame = .zero
mapView = GMSMapView(options: options)
view = mapView
构建并运行应用,您应该会看到一个以伦敦西南为中心的地图。
显示 Navigation SDK 产品使用条款对话框
将以下代码添加到与上一个代码相同的 loadView()
方法的 ViewController.swift
中。系统会显示 Navigation SDK 最终用户使用条款。如果未被接受,系统将不会启用导航。
// Show the terms and conditions.
let companyName = "Navigation SDK Codelab"
GMSNavigationServices.showTermsAndConditionsDialogIfNeeded(withCompanyName: companyName) { termsAccepted in
if termsAccepted {
// Enable navigation if the user accepts the terms.
self.mapView.isNavigationEnabled = true
// Request authorization for alert notifications which deliver guidance instructions
// in the background.
} else {
// Handle the case when the user rejects the terms and conditions.
}
}
构建并运行应用,即可看到对话框。
7. 为按键导航事件添加监听器
此步骤将向您介绍如何为关键事件(例如到达目的地或司机重选路线)设置监听器。
如需监听这些事件,您的视图控制器必须采用 GMSNavigatorListener
协议。
将此协议添加到 ViewController.swift
中的类定义。
class ViewController: UIViewController,
GMSNavigatorListener {
现在,添加一行代码以在 loadView():
中设置监听器
// Add a listener for GMSNavigator.
mapView.navigator?.add(self)
最后,向您的类添加两个方法来处理所引发的事件。
// Listener to handle arrival events.
func navigator(_ navigator: GMSNavigator, didArriveAt waypoint: GMSNavigationWaypoint) {
print("You have arrived at: \(waypoint.title)")
}
// Listener for route change events.
func navigatorDidChangeRoute(_ navigator: GMSNavigator) {
print("The route has changed.")
}
8. 设置目的地并开始导航
本部分将介绍如何设置目的地并启动导航指引。
为导航逻辑创建一个新函数。
首先,向 ViewController
添加一个名为 startNav()
的新函数。该文件将包含用于设置目的地并开始导航的逻辑。
// Create a route and start guidance.
@objc func startNav() {
}
为目标位置创建一个 Waypoint
。
接下来,创建包含单个航点的目的地数组。
// Create a route and start guidance.
@objc func startNav() {
var destinations = [GMSNavigationWaypoint]()
destinations.append(
GMSNavigationWaypoint.init(
placeID: "ChIJH-tBOc4EdkgRJ8aJ8P1CUxo",
title: "Trafalgar Square")!)
}
调用 setDestinations()
并处理响应。
接下来,调用 setDestinations
并处理返回的 GMSRouteStatus
。
如果 GMSRouteStatus
为“OK”,则通过在 mapView
的 navigator
对象上设置 isGuidanceActive=true
来启动导航。否则,输出一条语句以表明存在错误。
如果返回的 GMSRouteStatus
值为“OK”,则通过调用 mapView.locationSimulator.simulateLocationsAlongExistingRoute()
开始模拟沿路线驾驶。
// Create a route and start guidance.
@objc func startNav() {
var destinations = [GMSNavigationWaypoint]()
destinations.append(
GMSNavigationWaypoint.init(
placeID: "ChIJH-tBOc4EdkgRJ8aJ8P1CUxo",
title: "Trafalgar Square")!)
mapView.navigator?.setDestinations(
destinations
) { routeStatus in
guard routeStatus == .OK else {
print("Handle route statuses that are not OK.")
return
}
//If routeStatus is OK, start guidance.
self.mapView.navigator?.isGuidanceActive = true
//start simulating driving along the route. self.mapView.locationSimulator?.simulateLocationsAlongExistingRoute()
self.mapView.cameraMode = .following
}
}
处理常见的错误状态
更明确地处理 GMSRouteStatus
错误很有用,尤其是在调试新应用的初始问题时。例如,您可能会发现,由于调试设置,您最初会更频繁地收到位置信息权限、API 密钥或“未找到路线”错误,因此处理这些错误状态会很有用。
添加用于处理这些特定情况的代码,并向控制台输出一个语句。
mapView.navigator?.setDestinations(
destinations
) { routeStatus in
guard routeStatus == .OK else {
print("Handle route statuses that are not OK.")
switch routeStatus {
case .locationUnavailable:
print("Location unavailable.") //check permissions
case .noRouteFound:
print("No route found.") //check start location and destination
case .waypointError:
print("Waypoint error") //check Place ID
default:
print("Not sure what happened")
}
return
}
添加一个按钮以开始导航指南
最后,向界面添加一个按钮,并将其连接到 startNav 方法。使用以下代码创建一个名为 makeButton()
的方法。从 loadView()
调用 makeButton()
函数。
// Add a button to the view.
func makeButton() {
// A button to 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)
}
构建并运行您的应用。
注意:在以下位置运行代码:
startNav()
将调用
setDestinations()
方法,这会在使用的 1000 个目的地之后产生费用。如需了解详情,请参阅用量和结算。
9. 恭喜!
太棒了,您已到达目的地!
您已使用 Google Maps Platform Navigation SDK 创建了一个简单的应用,该应用可为目的地提供精细导航指导。
您已配置应用权限和 Navigation SDK 最终用户条款对话框,并使用地点 ID 指定了目的地。您已在应用中处理各种成功和错误状态。
10. 更进一步
如果您想进一步开发应用,请参阅以下主题以获取灵感。