You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
10 KiB

import UIKit
import AVFAudio
import AMapNaviKit
class AmapViewController: UIViewController {
// MARK: - 必须声明为强引用
private var driveManager: AMapNaviDriveManager!
private var driveView: AMapNaviDriveView!
private let speechSynthesizer = AVSpeechSynthesizer()
private var startPoint: AMapNaviPoint!
private var endPoint: AMapNaviPoint!
// 自定义初始化方法
init(startpos: String, endpos: String) {
super.init(nibName: nil, bundle: nil)
self.startPoint = AmapViewController.parseCoord(from: startpos)
self.endPoint = AmapViewController.parseCoord(from: endpos)
print("导航---------------------: \(startPoint) \(endPoint)")
}
// 解析 "lat,lng" -> AMapNaviPoint
private static func parseCoord(from string: String) -> AMapNaviPoint? {
let components = string.split(separator: ",")
guard components.count == 2,
let lng = Double(components[0]),
let lat = Double(components[1]) else {
print("❌ 无效坐标格式: \(string)")
return nil
}
return AMapNaviPoint.location(withLatitude: lat, longitude: lng)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
setupAMapComponents()
}
private func setupAMapComponents() {
// 1. 初始化 DriveView(必须在主线程)
print("导航------------------ setupAMapComponents_1")
DispatchQueue.main.async {
print("导航------------------ setupAMapComponents_2")
self.driveView = AMapNaviDriveView(frame: self.view.bounds)
print("导航------------------ setupAMapComponents_3")
self.driveView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
print("导航------------------ setupAMapComponents_4")
self.driveView.delegate = self
print("导航------------------ setupAMapComponents_5")
self.view.addSubview(self.driveView)
print("导航------------------ setupAMapComponents_6")
// 2. 初始化 DriveManager
self.driveManager = AMapNaviDriveManager.sharedInstance()
print("导航------------------ setupAMapComponents_7")
self.driveManager.delegate = self
print("导航------------------ setupAMapComponents_8")
self.driveManager.allowsBackgroundLocationUpdates = true
print("导航------------------ setupAMapComponents_9")
// 3. 确保对象非空再关联
if let manager = self.driveManager, let view = self.driveView {
print("导航------------------ setupAMapComponents_10")
manager.addDataRepresentative(view)
print("导航------------------ setupAMapComponents_11")
self.startNavigation()
print("导航------------------ setupAMapComponents_12")
} else {
print("Error: driveManager or driveView is nil")
}
print("导航------------------ setupAMapComponents_13")
}
}
private func startNavigation() {
// print("导航------------------ startNavigation_1")
// let startPoint = AMapNaviPoint.location(withLatitude: 39.989614, longitude: 116.481763)!
// print("导航------------------ startNavigation_2")
// let endPoint = AMapNaviPoint.location(withLatitude: 39.983456, longitude: 116.315495)!
// print("导航------------------ startNavigation_3")
driveManager.calculateDriveRoute(
withStart: [startPoint],
end: [endPoint],
wayPoints: nil,
drivingStrategy: .drivingStrategySingleDefault
)
print("导航------------------ startNavigation_4")
}
@objc private func exitNavigation() {
print("导航------------------ 退出导航,清理资源")
// 停止导航
driveManager.stopNavi()
driveManager.removeDataRepresentative(driveView)
driveManager.delegate = nil
// 移除导航视图
driveView.delegate = nil
driveView.removeFromSuperview()
driveView = nil
// 销毁导航管理器
driveManager = nil
// 关闭当前页面,视情况而定
// 如果你用的是导航控制器,可以pop
navigationController?.popViewController(animated: true)
// 或者如果是present出来的,dismiss
// dismiss(animated: true, completion: nil)
}
}
// MARK: - 代理方法
extension AmapViewController: AMapNaviDriveViewDelegate, AMapNaviDriveManagerDelegate {
//View回调
func driveViewCloseButtonClicked(_ driveView: AMapNaviDriveView) {
print("导航界面退出按钮被点击")
// 停止导航并清理
driveManager.stopNavi()
driveManager.removeDataRepresentative(driveView)
driveManager.delegate = nil
driveView.delegate = nil
driveView.removeFromSuperview()
// 返回到 Flutter 页面
self.dismiss(animated: true, completion: nil)
}
func driveView(_ driveView: AMapNaviDriveView, didChange showMode: AMapNaviDriveViewShowMode) {
print("导航界面显示模式改变:\(showMode.rawValue)")
}
func driveView(_ driveView: AMapNaviDriveView, didChange trackMode: AMapNaviViewTrackingMode) {
print("导航界面跟随模式改变:\(trackMode.rawValue)")
}
func driveView(_ driveView: AMapNaviDriveView, didChangeOrientation isLandscape: Bool) {
print("导航界面横竖屏切换:isLandscape = \(isLandscape)")
}
func driveView(_ driveView: AMapNaviDriveView, didChangeDayNightType showStandardNightType: Bool) {
print("导航界面白天/黑夜模式切换:isNight = \(showStandardNightType)")
}
func driveViewEdgePadding(_ driveView: AMapNaviDriveView) -> UIEdgeInsets {
// 你可以根据自己 UI 布局返回合适的内边距,防止遮挡
let padding = UIEdgeInsets(top: 100, left: 50, bottom: 80, right: 60)
print("请求导航界面可视区域边距:\(padding)")
return padding
}
//导航回调
func driveManager(_ driveManager: AMapNaviDriveManager, error: Error) {
print("导航------------------ ❌ 发生错误: \(error.localizedDescription)")
}
func driveManager(onCalculateRouteSuccess driveManager: AMapNaviDriveManager){
print("导航------------------ ✅ 路线规划成功(旧方法)")
driveManager.startGPSNavi()
}
func driveManager(_ driveManager: AMapNaviDriveManager, onCalculateRouteSuccessWith type: AMapNaviRoutePlanType) {
print("导航------------------ 路径规划成功,类型: \(type.rawValue)")
driveManager.startGPSNavi()
}
func driveManager(_ driveManager: AMapNaviDriveManager, onCalculateRouteFailure error: Error) {
print("导航------------------ ❌ 路线规划失败: \(error.localizedDescription)")
}
func driveManager(_ driveManager: AMapNaviDriveManager, onCalculateRouteFailure error: Error, routePlanType type: AMapNaviRoutePlanType) {
print("导航------------------ ❌ 路线规划失败(新方法): \(error.localizedDescription),类型: \(type.rawValue)")
}
func driveManager(_ driveManager: AMapNaviDriveManager, didStartNavi naviMode: AMapNaviMode) {
print("导航------------------ 🚗 已开始导航,模式: \(naviMode.rawValue)")
}
func driveManagerNeedRecalculateRoute(forYaw driveManager: AMapNaviDriveManager) {
print("导航------------------ 出现偏航,需要重新计算路径")
}
func driveManagerNeedRecalculateRoute(forTrafficJam driveManager: AMapNaviDriveManager) {
print("导航------------------ 遇到拥堵,重新规划路线")
}
func driveManager(_ driveManager: AMapNaviDriveManager, onArrivedWayPoint wayPointIndex: Int) {
print("导航------------------ 到达途经点索引:\(wayPointIndex)")
}
func driveManagerIsNaviSoundPlaying(_ driveManager: AMapNaviDriveManager) -> Bool {
print("导航------------------ 🔊 正在判断是否在播报语音")
return false // 如果你有 TTS 系统播报时需返回 true
}
func driveManager(_ driveManager: AMapNaviDriveManager, playNaviSound soundString: String, soundStringType: AMapNaviSoundType) {
print("导航------------------ 📢 导航播报: \(soundString),类型: \(soundStringType.rawValue)")
// 示例:使用 AVSpeechSynthesizer 播放语音
let utterance = AVSpeechUtterance(string: soundString)
utterance.voice = AVSpeechSynthesisVoice(language: "zh-CN")
speechSynthesizer.speak(utterance)
}
func driveManagerDidEndEmulatorNavi(_ driveManager: AMapNaviDriveManager) {
print("导航------------------ 🛑 模拟导航结束")
}
func driveManager(onArrivedDestination driveManager: AMapNaviDriveManager) {
print("导航------------------ 🎯 到达目的地")
}
func driveManager(_ driveManager: AMapNaviDriveManager, onNaviPlay ringType: AMapNaviRingType) {
print("导航------------------ 🔔 播放提示音,类型: \(ringType.rawValue)")
}
func driveManager(_ driveManager: AMapNaviDriveManager, update gpsSignalStrength: AMapNaviGPSSignalStrength) {
print("导航------------------ 📡 GPS信号强度: \(gpsSignalStrength.rawValue)")
}
func driveManager(_ driveManager: AMapNaviDriveManager, postRouteNotification notifyData: AMapNaviRouteNotifyData) {
print("导航------------------ 📌 路线通知信息: \(notifyData)")
}
func driveManager(_ driveManager: AMapNaviDriveManager, onSuggestChangeMainNaviRoute suggestChangeMainNaviRouteInfo: AMapNaviSuggestChangeMainNaviRouteInfo) {
print("导航------------------ 🔄 建议切换主导航路线: \(suggestChangeMainNaviRouteInfo)")
}
}