diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 3d1ae458c..e1ca0f551 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -132,4 +132,14 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/data/services/ble_manager.dart b/lib/data/services/ble_manager.dart
index 86d1572ef..1a3b2921c 100644
--- a/lib/data/services/ble_manager.dart
+++ b/lib/data/services/ble_manager.dart
@@ -663,6 +663,8 @@ class BleManager extends GetxService {
AppConfig.env('OPENAI_AGENT_ID') ?? 'personal_assistant';
final systemPrompt = AppConfig.agentsystemPrompt(openaiagentid);
final musicServiceType = AppConfig.env('APP_MUSICSERVICE_TYPE') ?? 'AUTO';
+ final navigationMode =
+ AppConfig.env('APP_NAVIGATION_MODE') ?? 'external_auto';
// 从Flutter资源包中加载.mcp.json
final jsonData = AppConfig.mcpConfig();
Logger.info('启动BLE服务,musicServiceType: ${musicServiceType}');
@@ -734,6 +736,7 @@ class BleManager extends GetxService {
'usertoken': jsonString,
'supportedLanguages': supportedLanguages,
'musicServiceType': musicServiceType,
+ "navigationMode": navigationMode
};
// 记录日志(不记录敏感信息)
diff --git a/lib/modules/agent/controllers/agent_controller.dart b/lib/modules/agent/controllers/agent_controller.dart
index 78fa49473..3ad7a9657 100644
--- a/lib/modules/agent/controllers/agent_controller.dart
+++ b/lib/modules/agent/controllers/agent_controller.dart
@@ -4,7 +4,9 @@ import 'dart:ffi';
import 'dart:io';
import 'package:amap_service/amap_service.dart';
import 'package:http/http.dart' as http;
+import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
+import 'package:voitrans/data/models/appconfig.dart';
import 'package:voitrans/data/models/song_model.dart';
import 'package:voitrans/data/services/ble_manager.dart';
import 'package:voitrans/data/services/bluetooth_manager.dart';
@@ -172,7 +174,6 @@ class AgentController extends GetxController with WidgetsBindingObserver {
_setupTextInputListener(); //设置文本输入监听器
startVoiceInput(); //开启语音输入
-
// 监听应用生命周期:当应用切到后台/失焦时兜底结束按住说话,防止 onPointerUp 未触发
WidgetsBinding.instance.addObserver(this);
@@ -812,13 +813,22 @@ class AgentController extends GetxController with WidgetsBindingObserver {
if (card_navigation is Map) {
//导航
final start = card_navigation["start"] as String;
- final end = card_navigation["end"] as String;
+ final destination =
+ card_navigation["destination"] as String;
+ final end_longitude =
+ card_navigation["end_longitude"] as String;
+ final end_latitude =
+ card_navigation["end_latitude"] as String;
+ // End_longitude string `json:"end_longitude"` //目标点经度
+ // End_latitude string `json:"end_latitude"` //目标点纬度
final items = card_navigation['items'];
if (items != null) {
Future.delayed(Duration(seconds: 2), () {
// Logger.i(TAG, 'liwei-------- 打开导航页面: $start $end ');
// 2秒后执行的代码
- openNavigation(start, end, "");
+
+ openNavigation(start, destination, end_latitude,
+ end_longitude, "");
});
}
}
@@ -1855,8 +1865,19 @@ class AgentController extends GetxController with WidgetsBindingObserver {
}
//去导航
- void openNavigation(String start, String end, String ntype) {
- _navigationManager.open(start, end, ntype);
+ void openNavigation(String start, String destination, String endlatitude,
+ String endlongitude, String mode) {
+ final navigationMode =
+ AppConfig.env('APP_NAVIGATION_MODE') ?? 'external_auto';
+ if (navigationMode == 'internal_gaode') {
+ _navigationManager.open(start, "$endlongitude,$endlatitude", mode);
+ } else if (navigationMode == 'external_baidu') {
+ openBaiduMap(destination, mode);
+ } else if (navigationMode == 'external_gaode') {
+ openGaodeMap(destination, endlatitude, destination, mode);
+ } else if (navigationMode == 'external_google') {
+ openGoogleMap(destination, mode);
+ }
}
// 打开图片查看器
@@ -2189,4 +2210,106 @@ class AgentController extends GetxController with WidgetsBindingObserver {
Get.snackbar('错误', '打开地图时发生错误');
}
}
+
+ /// 打开高德地图进行导航
+ Future openGaodeMap(
+ String destination,
+ String lat,
+ String lon,
+ String mode,
+ ) async {
+ try {
+ // 获取应用包名
+ final packageInfo = await PackageInfo.fromPlatform();
+
+ // 构建src参数(带平台前缀)
+ final String src = Platform.isAndroid
+ ? "android.${packageInfo.packageName}"
+ : "ios.${packageInfo.packageName}";
+
+ // 构建高德地图导航链接
+ final Uri uri = Uri(
+ scheme: 'androidamap',
+ host: 'navi',
+ queryParameters: {
+ 'poiname': destination, // 目的地地址
+ 'lat': lat,
+ 'lon': lon,
+ 'mode': mode.isNotEmpty ? mode : 'driving', // 导航模式,默认驾车
+ 'sourceApplication': src, // 来源标识
+ 'callnative': '1', // 优先调用原生应用
+ },
+ );
+
+ print('高德导航链接: ${uri.toString()}');
+ // final Uri testMapsUri = Uri.parse(
+ // 'androidamap://navi?sourceApplication=android.com.saitong.voitrans&lat=22.615274&lon=114.035576&poiname=深圳北站&dev=0&mode=driving');
+ // // 尝试打开高德地图应用
+ if (await canLaunchUrl(uri)) {
+ final bool launched = await launchUrl(
+ uri,
+ mode: LaunchMode.externalApplication,
+ );
+ if (!launched) {
+ print('高德地图已安装,但启动失败');
+ Get.snackbar('提示', '高德地图启动失败');
+ }
+ } else {
+ print('高德地图未安装');
+ Get.snackbar('提示', '请先安装高德地图应用');
+ }
+ } catch (e) {
+ print('打开地图失败: $e');
+ Get.snackbar('错误', '打开地图时发生错误');
+ }
+ }
+
+ /// 打开Baidu地图进行导航
+ Future openBaiduMap(
+ String destination,
+ String mode,
+ ) async {
+ try {
+ // 地址和城市(已编码的字符串也可以直接使用)
+ // String destination = "深圳北站";
+ // String city = "深圳";
+
+ // 构建正确的导航链接
+ final Uri appUri = Uri(
+ scheme: 'baidumap',
+ host: 'map',
+ path: 'direction', // 使用direction端点而非navi
+ queryParameters: {
+ 'destination': destination,
+ // 'city': '深圳',
+ 'mode': mode, // 明确导航模式
+ 'src': 'com.saitong.voitrans', // 带平台前缀的src参数
+ },
+ );
+
+ print('生成的链接: ${appUri.toString()}');
+
+ if (await canLaunchUrl(appUri)) {
+ await launchUrl(appUri, mode: LaunchMode.externalApplication);
+ } else {
+ print('无法打开百度地图,请检查是否已安装');
+ }
+
+ // final packageInfo = await PackageInfo.fromPlatform();
+ // String packageName = packageInfo.packageName;
+ // // 方案1: 尝试使用Google Maps应用的URL scheme
+ // // final Uri googleMapsUri = Uri.parse(url);
+ // // 简化版链接(仅包含必要参数)
+ // final Uri testUri = Uri.parse(
+ // 'baidumap://map/navi?location=$end_latitude,$end_longitude&coord_type=bd09ll&src$packageName');
+ // if (await canLaunchUrl(testUri)) {
+ // await launchUrl(testUri, mode: LaunchMode.externalApplication);
+ // } else {
+ // print('打开地图失败');
+ // }
+ } catch (e) {
+ print('打开地图失败: $e');
+ Get.snackbar('错误', '打开地图时发生错误');
+ }
+ }
}
diff --git a/lib/modules/agent/views/message_bubble.dart b/lib/modules/agent/views/message_bubble.dart
index eda6c114f..63615d5e0 100644
--- a/lib/modules/agent/views/message_bubble.dart
+++ b/lib/modules/agent/views/message_bubble.dart
@@ -2,6 +2,7 @@ import 'package:voitrans/core/utils/logger.dart';
import 'package:voitrans/modules/agent/views/google_navigation_card.dart';
import 'package:voitrans/modules/agent/views/music_card.dart';
import 'package:voitrans/modules/agent/views/qqmusic_card.dart';
+import 'package:voitrans/modules/agent/views/weather_baidu.dart';
import '../../../data/models/song_model.dart';
import '../../../modules/agent/views/navigation_card.dart';
@@ -258,6 +259,7 @@ class MessageBubble extends GetView {
return buildQQMusicContent(context, songList);
}
} else if (meta!.keys.contains('maps_weather')) {
+ //高德的
final maps_weather = meta!['maps_weather'] as Map;
final city = maps_weather['city'];
if (city != null) {
@@ -273,6 +275,25 @@ class MessageBubble extends GetView {
daylist,
);
}
+ } else if (meta!.keys.contains('map_weather')) {
+ //百度的
+ final map_weather = meta!['map_weather'] as Map;
+ final status = map_weather['status'];
+ if (status == 0) {
+ final result = map_weather['result'] as Map;
+ final city = result["location"]["city"] as String? ?? '';
+ final rawList = result['forecasts'] as List? ?? [];
+ final daylist =
+ rawList.map((e) => Map.from(e)).toList();
+ final now = daylist.isNotEmpty ? daylist[0] : {};
+ //天气
+ return buildWeatherBaiduContent(
+ context,
+ city,
+ now,
+ daylist,
+ );
+ }
} else if (meta!.keys.contains('card_travel')) {
final rawList = meta!['card_travel']['items'] as List? ?? [];
final travellist =
@@ -286,6 +307,8 @@ class MessageBubble extends GetView {
maps_route_navigation["card_navigation"] as Map;
final start = card_navigation['start'] as String? ?? '';
final end = card_navigation['end'] as String? ?? '';
+ final end_longitude = card_navigation["end_longitude"] as String;
+ final end_latitude = card_navigation["end_latitude"] as String;
final destination = card_navigation['destination'] as String? ?? '';
final rawList = card_navigation['items'] as List? ?? null;
if (rawList != null) {
@@ -299,6 +322,8 @@ class MessageBubble extends GetView {
return navigationCard(context,
start: start,
end: end,
+ endlatitude: end_latitude,
+ endlongitude: end_longitude,
destination: destination,
modes: list,
navigation: navigation);
diff --git a/lib/modules/agent/views/navigation_card.dart b/lib/modules/agent/views/navigation_card.dart
index b5d904fff..edb277bd9 100644
--- a/lib/modules/agent/views/navigation_card.dart
+++ b/lib/modules/agent/views/navigation_card.dart
@@ -45,6 +45,8 @@ Widget navigationCard(
BuildContext context, {
required String start,
required String end,
+ required String endlatitude,
+ required String endlongitude,
required String destination,
required List