diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index dda0379b0..4ef33cfa7 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -3,6 +3,8 @@ PODS:
- AMapNavi (~> 10.0.900)
- Flutter
- AMapFoundation (1.8.2)
+ - AMapLocation (2.10.0):
+ - AMapFoundation (>= 1.8.0)
- AMapNavi (10.0.900):
- AMapFoundation (>= 1.8.2)
- audio_waveforms (0.0.1):
@@ -54,6 +56,9 @@ PODS:
- libwebp/sharpyuv (1.5.0)
- libwebp/webp (1.5.0):
- libwebp/sharpyuv
+ - location_service (0.0.1):
+ - AMapLocation (~> 2.10.0)
+ - Flutter
- Mantle (2.2.0):
- Mantle/extobjc (= 2.2.0)
- Mantle/extobjc (2.2.0)
@@ -98,6 +103,7 @@ DEPENDENCIES:
- flutter_tts (from `.symlinks/plugins/flutter_tts/ios`)
- fluwx (from `.symlinks/plugins/fluwx/ios`)
- haptic_feedback (from `.symlinks/plugins/haptic_feedback/ios`)
+ - location_service (from `.symlinks/plugins/location_service/ios`)
- ota (from `.symlinks/plugins/ota/ios`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- record_darwin (from `.symlinks/plugins/record_darwin/ios`)
@@ -107,6 +113,7 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- AMapFoundation
+ - AMapLocation
- AMapNavi
- FBAEMKit
- FBSDKCoreKit
@@ -146,6 +153,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/fluwx/ios"
haptic_feedback:
:path: ".symlinks/plugins/haptic_feedback/ios"
+ location_service:
+ :path: ".symlinks/plugins/location_service/ios"
ota:
:path: ".symlinks/plugins/ota/ios"
permission_handler_apple:
@@ -160,6 +169,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
amap_service: 1c3e7e07f51cbbdff03719a4a079c60d015c1c0b
AMapFoundation: 9885c48fc3a78fdfb84a0299a2293e56ea3c9fec
+ AMapLocation: 5248aec2455ebb5d104b367813c946430a2ee033
AMapNavi: fceb4715f9a3b5a25f330facebee2aa2bdba42dd
audio_waveforms: a6dde7fe7c0ea05f06ffbdb0f7c1b2b2ba6cedcf
classic_bluetooth: c146e1618e867a47fa7ab79a3bf262e7d69d557d
@@ -177,6 +187,7 @@ SPEC CHECKSUMS:
fluwx: 6bf9c5a3a99ad31b0de137dd92370a0d10a60f4b
haptic_feedback: fd1d8509833f58f164fc12122c0357fa9b2750e0
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
+ location_service: fab4ef23d473296a215c49e12c129e466574d94e
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
ota: 20c3e522c57e7ba70ce118109e73650acc9fec76
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
diff --git a/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift b/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift
index 9f4ac434a..e5035bf17 100644
--- a/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift
+++ b/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift
@@ -12,7 +12,11 @@ import music_service
protocol AgentServiceListener: AnyObject {
func onEvent(eventName: String, data: [String: Any])
}
-
+extension Notification.Name {
+ static let navigationdEvent = Notification.Name("navigationdEvent") //导航事件
+ static let locationstartEvent = Notification.Name("locationstartEvent") //启动定位
+ static let updatelocationEvent = Notification.Name("updatelocationEvent") //更新位置事件
+}
class AgentServiceImpl: NSObject {
private let TAG = "AgentServiceImpl"
@@ -55,6 +59,7 @@ class AgentServiceImpl: NSObject {
private let maxIdleSeconds: TimeInterval = 10
internal var audioPlayer: AudioPlayer?
+ private var locationInfo:[String: String]?
internal let logger = OSLog(subsystem: "com.yunqiinnovation.agent_service", category: "AgentServiceImpl")
@@ -161,7 +166,9 @@ class AgentServiceImpl: NSObject {
sendError("Azure语音区域缺失", code: "CONFIG_ERROR")
return false
}
-
+ //启动定位服务
+ NotificationCenter.default.post(name: .locationstartEvent, object: nil)
+ addlocationmonitor()
if let mcpServer = config["mcpServer"] as? String {
self.mcpServer = mcpServer
}
@@ -441,7 +448,10 @@ class AgentServiceImpl: NSObject {
var messages: [[String: Any]] = []
if !systemPrompt.isEmpty {
- messages.append(chatApiService.createSystemMessage(content: systemPrompt))
+
+ let info: [String: String] = self.locationInfo ?? ["user_location": "还未获取到位置信息", "user_lat": "未开启定位", "user_lng": "未开启定位"]
+ let _systemPrompt = fillTemplate(systemPrompt, with: info)
+ messages.append(chatApiService.createSystemMessage(content: _systemPrompt))
os_log("添加系统提示消息", log: logger, type: .info)
}
@@ -690,6 +700,27 @@ class AgentServiceImpl: NSObject {
MusicService.shared.playPlaylist(songs: songs)
}
+ // 添加定位监听
+ private func addlocationmonitor(){
+ // 通常放在启动后或模块初始化时
+ NotificationCenter.default.addObserver(
+ forName: .updatelocationEvent,
+ object: nil,
+ queue: .main
+ ) { notification in
+ if let info = notification.userInfo as? [String: String] {
+ print("📤 地址信息:\(info)")
+ self.locationInfo = info
+ }
+ }
+ }
+ func fillTemplate(_ template: String, with values: [String: String]) -> String {
+ var result = template
+ for (key, value) in values {
+ result = result.replacingOccurrences(of: "{\(key)}", with: value)
+ }
+ return result
+ }
func clearChatHistory() -> Bool {
chatHistory.removeAll()
diff --git a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift
index 610ccdc00..1d7b7746d 100644
--- a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift
+++ b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift
@@ -67,7 +67,7 @@ public class SystemFunctionHandler: NSObject {
registerGetCurrentTimeFunction(client: client)
// 注册获取当前位置函数
- registerGetCurrentLocationFunction(client: client)
+ // registerGetCurrentLocationFunction(client: client)
// 注册媒体控制函数
registerMediaPlayFunction(client: client)
diff --git a/local_plugins/location_service/ios/Classes/LocationService.swift b/local_plugins/location_service/ios/Classes/LocationService.swift
new file mode 100644
index 000000000..d71179ee3
--- /dev/null
+++ b/local_plugins/location_service/ios/Classes/LocationService.swift
@@ -0,0 +1,131 @@
+import Foundation
+import AMapLocationKit
+
+extension Notification.Name {
+ static let locationstartEvent = Notification.Name("locationstartEvent") //启动定位
+ static let updatelocationEvent = Notification.Name("updatelocationEvent") //更新位置事件
+}
+class LocationService: NSObject {
+ static let shared = LocationService()
+ private let TAG = "LocationService"
+
+ private var locationManager: AMapLocationManager!
+ private var currentLocation: CLLocation?
+ private var currentReGeocode: AMapLocationReGeocode?
+ private var initialized = false
+
+ private override init() {
+ super.init()
+ }
+
+ // 初始化定位服务
+ func initialize() {
+ if initialized { return }
+ print("\(TAG)--------- 初始化高德定位服务")
+
+ locationManager = AMapLocationManager()
+ locationManager.delegate = self
+
+ locationManager.desiredAccuracy = kCLLocationAccuracyBest // 定位精度
+ locationManager.distanceFilter = 10.0 // 移动距离阈值(单位:米)
+ locationManager.locatingWithReGeocode = true // 是否返回逆地理编码信息
+ locationManager.allowsBackgroundLocationUpdates = true // 是否允许后台定位
+ locationManager.locationTimeout = 10 // 定位超时时间(秒)
+ locationManager.reGeocodeTimeout = 5 // 逆地理编码超时时间(秒)
+
+ locationManager.startUpdatingLocation()
+
+ initialized = true
+ }
+
+ // 获取缓存的位置信息
+ func getCachedLocation() -> [String: String]? {
+ guard let location = currentLocation else { return nil }
+
+ var locationInfo: [String: String] = [
+ "user_lat": "\(location.coordinate.latitude)",
+ "user_lng": "\(location.coordinate.longitude)"
+ ]
+
+ if let regeocode = currentReGeocode {
+ let address = [
+ regeocode.province, // 省
+ regeocode.city, // 市
+ regeocode.district, // 区
+ regeocode.street, // 街道
+ regeocode.number // 门牌号
+ ].compactMap { $0 }.joined(separator: "")
+
+ locationInfo["user_location"] = address
+ }
+
+ return locationInfo
+ }
+
+ // 获取当前位置(带回调)
+ func getCurrentLocation(completion: @escaping ([String: String]?, Error?) -> Void) {
+ if let cached = getCachedLocation() {
+ completion(cached, nil)
+ } else {
+ let error = NSError(
+ domain: "LocationService",
+ code: -1,
+ userInfo: [NSLocalizedDescriptionKey: "当前位置还未获取"]
+ )
+ completion(nil, error)
+ }
+ }
+
+ // 停止定位服务
+ func stop() {
+ locationManager.stopUpdatingLocation()
+ locationManager = nil
+ currentLocation = nil
+ currentReGeocode = nil
+ initialized = false
+ }
+}
+
+// MARK: - AMapLocationManagerDelegate
+extension LocationService: AMapLocationManagerDelegate {
+ // 定位更新回调
+ func amapLocationManager(_ manager: AMapLocationManager!, didUpdate location: CLLocation!, reGeocode: AMapLocationReGeocode!) {
+ currentLocation = location
+ currentReGeocode = reGeocode
+
+ print("\(TAG)--------- 定位更新: \(location.coordinate.latitude), \(location.coordinate.longitude)")
+
+ var locationInfo: [String: String] = [
+ "user_lat": "\(location.coordinate.latitude)",
+ "user_lng": "\(location.coordinate.longitude)"
+ ]
+ if let regeocode = currentReGeocode {
+ let address = [
+ reGeocode.province, // 省
+ reGeocode.city, // 市
+ reGeocode.district, // 区
+ reGeocode.street, // 街道
+ reGeocode.number // 门牌号
+ ].compactMap { $0 }.joined(separator: "")
+ print("\(TAG)--------- 定位地址: \(address)")
+ locationInfo["user_location"] = address
+ }
+
+
+ NotificationCenter.default.post(
+ name: .updatelocationEvent,
+ object: nil,
+ userInfo: locationInfo
+ )
+ }
+
+ // 定位失败回调
+ func amapLocationManager(_ manager: AMapLocationManager!, didFailWithError error: Error!) {
+ print("\(TAG)--------- 定位失败: \(error.localizedDescription)")
+ }
+
+ // 权限变更回调
+ func amapLocationManager(_ manager: AMapLocationManager!, doRequireLocationAuth locationManager: CLLocationManager!) {
+ locationManager.requestWhenInUseAuthorization()
+ }
+}
diff --git a/local_plugins/location_service/ios/Classes/LocationServicePlugin.swift b/local_plugins/location_service/ios/Classes/LocationServicePlugin.swift
new file mode 100644
index 000000000..ad30a36f7
--- /dev/null
+++ b/local_plugins/location_service/ios/Classes/LocationServicePlugin.swift
@@ -0,0 +1,44 @@
+import Flutter
+import UIKit
+import AMapLocationKit
+
+public class LocationServicePlugin: NSObject, FlutterPlugin {
+ private static var channel: FlutterMethodChannel?
+
+ public static func register(with registrar: FlutterPluginRegistrar) {
+ let channel = FlutterMethodChannel(name: "com.yunqiinnovation.location_service", binaryMessenger: registrar.messenger())
+ let instance = LocationServicePlugin()
+ // 必须先设置隐私合规
+ DispatchQueue.main.async {
+ // 2. API Key
+ AMapServices.shared()?.apiKey = "aa60a03be9f6531bcc64029e60f95d03"
+ AMapServices.shared().enableHTTPS = true
+ // 3. 打印验证(调试用)
+ print("高德SDK初始化完成")
+ }
+ registrar.addMethodCallDelegate(instance, channel: channel)
+ self.channel = channel
+ instance.addstartlocationmonitor()
+ }
+
+ public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
+ switch call.method {
+ case "location":
+ result(nil)
+ default:
+ result(FlutterMethodNotImplemented)
+ }
+ }
+
+ private func addstartlocationmonitor(){
+ // 通常放在启动后或模块初始化时
+ NotificationCenter.default.addObserver(
+ forName: .locationstartEvent,
+ object: nil,
+ queue: .main
+ ) { notification in
+ print("📥 收到 启动定位服务事件")
+ LocationService.shared.initialize()
+ }
+ }
+}
diff --git a/local_plugins/location_service/ios/location_service.podspec b/local_plugins/location_service/ios/location_service.podspec
index b5409ce22..549e6c473 100644
--- a/local_plugins/location_service/ios/location_service.podspec
+++ b/local_plugins/location_service/ios/location_service.podspec
@@ -13,17 +13,15 @@ A new Flutter project.
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
- s.source_files = 'location_service/Sources/location_service/**/*'
+ s.source_files = 'Classes/**/*'
s.dependency 'Flutter'
- s.platform = :ios, '12.0'
+ s.dependency 'AMapLocation', '~> 2.10.0'
- # Flutter.framework does not contain a i386 slice.
- s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
+ s.static_framework = true
+ s.pod_target_xcconfig = {
+ 'DEFINES_MODULE' => 'YES',
+ 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386'
+ }
+ s.platform = :ios, '12.0'
s.swift_version = '5.0'
-
- # If your plugin requires a privacy manifest, for example if it uses any
- # required reason APIs, update the PrivacyInfo.xcprivacy file to describe your
- # plugin's privacy impact, and then uncomment this line. For more information,
- # see https://developer.apple.com/documentation/bundleresources/privacy_manifest_files
- # s.resource_bundles = {'location_service_privacy' => ['location_service/Sources/location_service/PrivacyInfo.xcprivacy']}
end
diff --git a/local_plugins/location_service/ios/location_service/Package.swift b/local_plugins/location_service/ios/location_service/Package.swift
deleted file mode 100644
index 0b0dd0fbd..000000000
--- a/local_plugins/location_service/ios/location_service/Package.swift
+++ /dev/null
@@ -1,32 +0,0 @@
-// swift-tools-version: 5.9
-// The swift-tools-version declares the minimum version of Swift required to build this package.
-
-import PackageDescription
-
-let package = Package(
- name: "location_service",
- platforms: [
- .iOS("12.0")
- ],
- products: [
- .library(name: "location-service", targets: ["location_service"])
- ],
- dependencies: [],
- targets: [
- .target(
- name: "location_service",
- dependencies: [],
- resources: [
- // If your plugin requires a privacy manifest, for example if it uses any required
- // reason APIs, update the PrivacyInfo.xcprivacy file to describe your plugin's
- // privacy impact, and then uncomment these lines. For more information, see
- // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files
- // .process("PrivacyInfo.xcprivacy"),
-
- // If you have other resources that need to be bundled with your plugin, refer to
- // the following instructions to add them:
- // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package
- ]
- )
- ]
-)
diff --git a/local_plugins/location_service/ios/location_service/Sources/location_service/LocationServicePlugin.swift b/local_plugins/location_service/ios/location_service/Sources/location_service/LocationServicePlugin.swift
deleted file mode 100644
index 1b6f10f28..000000000
--- a/local_plugins/location_service/ios/location_service/Sources/location_service/LocationServicePlugin.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-import Flutter
-import UIKit
-
-public class LocationServicePlugin: NSObject, FlutterPlugin {
- public static func register(with registrar: FlutterPluginRegistrar) {
- let channel = FlutterMethodChannel(name: "location_service", binaryMessenger: registrar.messenger())
- let instance = LocationServicePlugin()
- registrar.addMethodCallDelegate(instance, channel: channel)
- }
-
- public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
- switch call.method {
- case "getPlatformVersion":
- result("iOS " + UIDevice.current.systemVersion)
- default:
- result(FlutterMethodNotImplemented)
- }
- }
-}
diff --git a/local_plugins/location_service/ios/location_service/Sources/location_service/PrivacyInfo.xcprivacy b/local_plugins/location_service/ios/location_service/Sources/location_service/PrivacyInfo.xcprivacy
deleted file mode 100644
index a34b7e2e6..000000000
--- a/local_plugins/location_service/ios/location_service/Sources/location_service/PrivacyInfo.xcprivacy
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
- NSPrivacyTrackingDomains
-
- NSPrivacyAccessedAPITypes
-
- NSPrivacyCollectedDataTypes
-
- NSPrivacyTracking
-
-
-
diff --git a/local_plugins/location_service/lib/location_service.dart b/local_plugins/location_service/lib/location_service.dart
index c662819c6..a760675ce 100644
--- a/local_plugins/location_service/lib/location_service.dart
+++ b/local_plugins/location_service/lib/location_service.dart
@@ -11,33 +11,8 @@ class LocationService {
'com.yunqiinnovation.location_service',
);
- // 事件通道 - 简化为只使用数据和状态通道
- late final EventChannel _dataEventChannel;
- late final EventChannel _statusEventChannel;
-
- // 事件流
- late final Stream _dataStream;
- late final Stream _statusStream;
-
- // 获取事件流
- Stream get onDataReceived => _dataStream;
-
- // 状态流直接传递原始数据
- Stream get onStatusUpdated => _statusStream;
-
// 内部构造函数
- LocationService._internal() {
- _dataEventChannel = const EventChannel(
- 'com.yunqiinnovation.music_service/data_events',
- );
- _statusEventChannel = const EventChannel(
- 'com.yunqiinnovation.music_service/status_events',
- );
-
- // 初始化事件流
- _dataStream = _dataEventChannel.receiveBroadcastStream();
- _statusStream = _statusEventChannel.receiveBroadcastStream();
- }
+ LocationService._internal() {}
Future