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.
165 lines
6.0 KiB
165 lines
6.0 KiB
import Foundation
|
|
import AMapNaviKit
|
|
import AVFoundation
|
|
|
|
public class AmapService: NSObject, AMapNaviDriveManagerDelegate {
|
|
public static let shared = AmapService()
|
|
|
|
private var driveManager: AMapNaviDriveManager?
|
|
private var startPoint: AMapNaviPoint?
|
|
private var endPoint: AMapNaviPoint?
|
|
private var isNavigating = false
|
|
|
|
private override init() {
|
|
super.init()
|
|
setupDriveManager()
|
|
}
|
|
|
|
private func setupDriveManager() {
|
|
// 使用单例模式初始化
|
|
driveManager = AMapNaviDriveManager.sharedInstance()
|
|
driveManager?.delegate = self
|
|
driveManager?.isUseInternalTTS = true
|
|
|
|
// 设置高德地图服务
|
|
// 1. 设置隐私合规
|
|
AMapServices.shared()?.enableHTTPS = true
|
|
AMapServices.shared()?.apiKey = "6144a636c24dc9f2e1e57f7597849cf7"
|
|
}
|
|
|
|
public func startNavigation(from start: String, to end: String) {
|
|
guard !isNavigating else {
|
|
print("导航已在进行中")
|
|
return
|
|
}
|
|
print("开始导航")
|
|
// 解析坐标
|
|
let startCoords = start.split(separator: ",").compactMap { Double($0.trimmingCharacters(in: .whitespaces)) }
|
|
let endCoords = end.split(separator: ",").compactMap { Double($0.trimmingCharacters(in: .whitespaces)) }
|
|
|
|
guard startCoords.count == 2, endCoords.count == 2 else {
|
|
print("坐标格式错误,应为'经度,纬度'")
|
|
return
|
|
}
|
|
|
|
// 创建导航点(注意:高德地图使用经纬度顺序)
|
|
startPoint = AMapNaviPoint.location(withLatitude: CGFloat(startCoords[1]),
|
|
longitude: CGFloat(startCoords[0]))
|
|
endPoint = AMapNaviPoint.location(withLatitude: CGFloat(endCoords[1]),
|
|
longitude: CGFloat(endCoords[0]))
|
|
|
|
if let start = startPoint, let end = endPoint {
|
|
isNavigating = true
|
|
|
|
// 使用推荐的默认策略(避让拥堵+速度优先+避免收费)
|
|
let strategy: AMapNaviDrivingStrategy = .drivingStrategySingleDefault
|
|
|
|
// 调用最新API(注意参数是数组)
|
|
let success = driveManager?.calculateDriveRoute(withStart: [start],
|
|
end: [end],
|
|
wayPoints: nil,
|
|
drivingStrategy: strategy) ?? false
|
|
|
|
if !success {
|
|
isNavigating = false
|
|
print("路径规划参数校验失败")
|
|
}
|
|
}
|
|
}
|
|
|
|
public func stopNavigation() {
|
|
driveManager?.stopNavi()
|
|
isNavigating = false
|
|
}
|
|
|
|
// MARK: - AMapNaviDriveManagerDelegate
|
|
|
|
public func driveManager(onCalculateRouteSuccess driveManager: AMapNaviDriveManager) {
|
|
print("Route calculation succeeded")
|
|
driveManager.startEmulatorNavi() // 使用模拟导航(测试用)
|
|
// 实际使用时改为:
|
|
// driveManager.startGPSNavi()
|
|
}
|
|
|
|
public func driveManager(_ driveManager: AMapNaviDriveManager, onCalculateRouteFailure error: Error) {
|
|
isNavigating = false
|
|
print("Route calculation failed: \(error.localizedDescription)")
|
|
}
|
|
|
|
public func driveManager(_ driveManager: AMapNaviDriveManager, playNaviSound soundString: String, soundStringType: AMapNaviSoundType) {
|
|
// 过滤空内容和不需要处理的播报类型
|
|
guard !soundString.isEmpty else { return }
|
|
|
|
switch soundStringType {
|
|
case .default:
|
|
// 默认导航提示(如"前方500米右转"等)
|
|
playSystemTTS(soundString)
|
|
|
|
case .navigationStart:
|
|
// 开始导航提示("开始导航"等)
|
|
playSystemTTS("准备出发," + soundString)
|
|
|
|
case .navigationEnd:
|
|
// 到达目的地提示
|
|
playSystemTTS(soundString + ",导航结束")
|
|
|
|
case .yaw:
|
|
// 偏航提示("您已偏航,正在重新规划路线"等)
|
|
playSystemTTS("注意:" + soundString)
|
|
|
|
case .interrupt:
|
|
// 重要打断播报(如急转弯警告等)
|
|
interruptCurrentSpeech()
|
|
playSystemTTS(soundString)
|
|
|
|
default:
|
|
// 其他未明确处理的类型使用默认播报
|
|
playSystemTTS(soundString)
|
|
}
|
|
}
|
|
|
|
public func playSystemTTS(_ text: String) {
|
|
let utterance = AVSpeechUtterance(string: text)
|
|
utterance.voice = AVSpeechSynthesisVoice(language: "zh-CN")
|
|
utterance.rate = 0.5 // 适当放慢语速
|
|
|
|
let synthesizer = AVSpeechSynthesizer()
|
|
synthesizer.speak(utterance)
|
|
}
|
|
|
|
public func interruptCurrentSpeech() {
|
|
AVSpeechSynthesizer().stopSpeaking(at: .immediate)
|
|
}
|
|
|
|
public func driveManager(_ driveManager: AMapNaviDriveManager, update naviInfo: AMapNaviInfo?) {
|
|
guard let naviInfo = naviInfo else { return }
|
|
|
|
let currentRoad = naviInfo.currentRoadName ?? "未知道路"
|
|
let nextRoad = naviInfo.nextRoadName ?? "未知道路"
|
|
let distance = naviInfo.routeRemainDistance
|
|
let time = naviInfo.routeRemainTime
|
|
|
|
print("""
|
|
当前道路: \(currentRoad)
|
|
下条道路: \(nextRoad)
|
|
剩余距离: \(distance)米
|
|
剩余时间: \(time)秒
|
|
""")
|
|
}
|
|
|
|
public func driveManager(_ driveManager: AMapNaviDriveManager, error: Error) {
|
|
isNavigating = false
|
|
print("Navigation error occurred: \(error.localizedDescription)")
|
|
}
|
|
|
|
public func driveManagerDidEndEmulatorNavi(_ driveManager: AMapNaviDriveManager) {
|
|
isNavigating = false
|
|
print("Emulator navigation ended")
|
|
}
|
|
|
|
deinit {
|
|
driveManager?.stopNavi()
|
|
driveManager?.delegate = nil
|
|
AMapNaviDriveManager.destroyInstance()
|
|
}
|
|
}
|
|
|