Flutter集成CarPlay后无法从POI界面启动导航地图求助
Flutter应用集成CarPlay后实现POI条目触发CarPlay内导航
需求
- 基于flutter_carplay插件开发的Flutter应用,点击CarPlay中POI界面的条目时,需在CarPlay内打开地图并导航至该条目对应的地点
复现步骤
- 创建Flutter应用并添加flutter_carplay插件
- 替换插件中的
FCPPointOfInterest.swift代码为下方修改后的版本 - 使用POI模板后尝试从CarPlay发起导航
修改后的FCPPointOfInterest.swift代码
// // FCPPointOfInterest.swift // Runner // // Created by Olaf Schneider on 15.02.22. // import CarPlay @available(iOS 14.0, *) class FCPPointOfInterest { private(set) var _super: CPPointOfInterest? private(set) var elementId: String private var latitude: Double private var longitude: Double private var title: String private var subtitle: String? private var summary: String? private var detailTitle: String? private var detailSubtitle: String? private var detailSummary: String? private var image: String? private var primaryButton: CPTextButton? private var objcPrimaryButton: FCPTextButton? private var secondaryButton: CPTextButton? private var objcSecondaryButton: FCPTextButton? static let maxPinImageSize: CGFloat = 40 init(obj: [String: Any]) { self.elementId = obj["_elementId"] as! String let lat = obj["latitude"] as! NSNumber self.latitude = lat.doubleValue let lng = obj["longitude"] as! NSNumber self.longitude = lng.doubleValue self.title = obj["title"] as! String self.subtitle = obj["subtitle"] as? String self.summary = obj["summary"] as? String self.detailTitle = obj["detailTitle"] as? String self.detailSubtitle = obj["detailSubtitle"] as? String self.detailSummary = obj["detailSummary"] as? String self.image = obj["image"] as? String let primaryButtonData = obj["primaryButton"] as? [String: Any] if primaryButtonData != nil { self.objcPrimaryButton = FCPTextButton(obj: primaryButtonData!) // 创建带所有必要参数的CPTextButton let button = CPTextButton( title: self.objcPrimaryButton?.get.title ?? "", textStyle: .normal, // 可根据需要改为.confirm handler: { [weak self] _ in self?.launchGoogleMapsWithCarPlay() } ) self.primaryButton = button } let secondaryButtonData = obj["secondaryButton"] as? [String: Any] if secondaryButtonData != nil { self.objcSecondaryButton = FCPTextButton(obj: secondaryButtonData!) self.secondaryButton = self.objcSecondaryButton?.get } } func launchGoogleMapsWithCarPlaytry() { // 生成带目标坐标的Google Maps链接 let urlString = "comgooglemaps://?daddr=\(latitude),\(longitude)&directionsmode=driving" // 检查Google Maps是否已安装 if let url = URL(string: urlString), UIApplication.shared.canOpenURL(url) { // 打开Google Maps UIApplication.shared.open(url, options: [:], completionHandler: nil) } else { // 如果未安装Google Maps,降级使用Apple Maps let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) let placemark = MKPlacemark(coordinate: coordinate) let mapItem = MKMapItem(placemark: placemark) let launchOptions: [String: Any] = [ MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving, MKLaunchOptionsShowsTrafficKey: true, MKLaunchOptionsMapTypeKey: MKMapType.standard.rawValue, ] mapItem.openInMaps(launchOptions: launchOptions) } } func launchGoogleMapsWithCarPlay() { // 检查应用是否处于CarPlay模式 guard let carPlayScene = UIApplication.shared.connectedScenes.first(where: { $0 is CPTemplateApplicationScene }) as? CPTemplateApplicationScene, let interfaceController = carPlayScene.delegate as? CPTemplateApplicationSceneDelegate else { // 如果未连接CarPlay,降级使用移动端导航 // launchMobileNavigation() return } // 生成针对CarPlay的Google Maps链接 let urlString = "comgooglemaps://?daddr=\(latitude),\(longitude)&directionsmode=driving" if let url = URL(string: urlString), UIApplication.shared.canOpenURL(url) { // 打开Google Maps UIApplication.shared.open(url, options: [:], completionHandler: nil) } else { // 如果未安装Google Maps,降级使用Apple Maps let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) let placemark = MKPlacemark(coordinate: coordinate) let mapItem = MKMapItem(placemark: placemark) let launchOptions: [String: Any] = [ MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving, MKLaunchOptionsShowsTrafficKey: true, MKLaunchOptionsMapTypeKey: MKMapType.standard.rawValue ] mapItem.openInMaps(launchOptions: launchOptions) } } // 移动端导航降级函数 private func launchMobileNavigation() { let urlString = "comgooglemaps://?daddr=\(latitude),\(longitude)&directionsmode=driving" if let url = URL(string: urlString), UIApplication.shared.canOpenURL(url) { UIApplication.shared.open(url, options: [:], completionHandler: nil) } else { let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) let placemark = MKPlacemark(coordinate: coordinate) let mapItem = MKMapItem(placemark: placemark) let launchOptions: [String: Any] = [ MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving, MKLaunchOptionsShowsTrafficKey: true, MKLaunchOptionsMapTypeKey: MKMapType.standard.rawValue ] mapItem.openInMaps(launchOptions: launchOptions) } } private func launchMapsApp() { if UIApplication.shared.canOpenURL(URL(string: "comgooglemaps://")!) { if let url = URL( string: "comgooglemaps://?daddr=\(latitude),\(longitude)&directionsmode=driving") { UIApplication.shared.open(url, options: [:], completionHandler: nil) } } else { if let url = URL( string: "https://www.google.com/maps/dir/?api=1&destination=\(latitude),\(longitude)&travelmode=driving" ) { UIApplication.shared.open(url, options: [:], completionHandler: nil) } } } var get: CPPointOfInterest { let location = MKMapItem( placemark: MKPlacemark( coordinate: CLLocationCoordinate2D(latitude: latitude, longitude: longitude))) var pinImage: UIImage? = nil if let image = self.image { let key = SwiftFlutterCarplayPlugin.registrar?.lookupKey(forAsset: image) pinImage = UIImage(named: key!) if let pImage = pinImage { if pImage.size.height > FCPPointOfInterest.maxPinImageSize || pImage.size.width > FCPPointOfInterest.maxPinImageSize { pinImage = pImage.resizeImageTo( size: CGSize( width: FCPPointOfInterest.maxPinImageSize, height: FCPPointOfInterest.maxPinImageSize)) } } } let poi = CPPointOfInterest( location: location, title: title, subtitle: subtitle, summary: summary, detailTitle: detailTitle, detailSubtitle: detailSubtitle, detailSummary: detailSummary, pinImage: pinImage) if let primaryButton = self.primaryButton { poi.primaryButton = primaryButton } if let secondaryButton = self.secondaryButton { poi.secondaryButton = secondaryButton } self._super = poi return poi } }
内容的提问来源于stack exchange,提问作者Ragul PR
相关产品推荐
相关产品推荐

