diff --git a/lib/data/services/navigation_manager.dart b/lib/data/services/navigation_manager.dart index 924ef0877..5604838c7 100644 --- a/lib/data/services/navigation_manager.dart +++ b/lib/data/services/navigation_manager.dart @@ -31,7 +31,11 @@ class NavigationManager extends GetxService { // await _amapervice.navigation(org, dis); } //导航 - Future open() async { - await _amapervice.open(); + Future open( + String start, + String end, + String ntype, + ) async { + await _amapervice.open(start, end, ntype); } } diff --git a/lib/modules/agent/controllers/agent_controller.dart b/lib/modules/agent/controllers/agent_controller.dart index 6e81b5ce7..12c459295 100644 --- a/lib/modules/agent/controllers/agent_controller.dart +++ b/lib/modules/agent/controllers/agent_controller.dart @@ -397,7 +397,7 @@ class AgentController extends GetxController { if (meta != null && meta is String && meta.isNotEmpty) { try { - metaResult = jsonDecode(meta); + metaResult = jsonDecode(meta) as Map; } catch (e) { Logger.e(TAG, '解析meta数据失败: $e'); } @@ -422,6 +422,16 @@ class AgentController extends GetxController { ); } } + if (metaResult.containsKey("card_navigation")) { + final start = metaResult["card_navigation"]["start"] as String; + final end = metaResult["card_navigation"]["end"] as String; + Logger.i(TAG, 'liwei-------- 打开导航页面: $start $end '); + Future.delayed(Duration(seconds: 2), () { + Logger.i(TAG, 'liwei-------- 打开导航页面: $start $end '); + // 2秒后执行的代码 + openNavigation(start, end, ""); + }); + } } } break; @@ -849,7 +859,7 @@ class AgentController extends GetxController { } //去导航 - void openNavigation() { - _navigationManager.open(); + void openNavigation(String start, String end, String ntype) { + _navigationManager.open(start, end, ntype); } } diff --git a/lib/modules/agent/views/message_bubble.dart b/lib/modules/agent/views/message_bubble.dart index 0d945fc65..4e037f1e6 100644 --- a/lib/modules/agent/views/message_bubble.dart +++ b/lib/modules/agent/views/message_bubble.dart @@ -284,6 +284,8 @@ class MessageBubble extends GetView { // 旅游 return _buildTravelContent(context, travellist); } else if (meta!.keys.contains('card_navigation')) { + final start = meta!['card_navigation']['start'] as String; + final end = meta!['card_navigation']['end'] as String; final destination = meta!['card_navigation']['destination'] as String; final rawList = meta!['card_navigation']['items'] as List; final list = rawList.map((e) => Map.from(e)).toList(); @@ -293,7 +295,11 @@ class MessageBubble extends GetView { print("导航实时数据 ${rawNavigation}"); // 导航 return navigationCard(context, - destination: destination, modes: list, navigation: navigation); + start: start, + end: end, + destination: destination, + modes: list, + navigation: navigation); } // if (message.contains('播放列表') || message.contains('音乐')) { @@ -1205,6 +1211,8 @@ class MessageBubble extends GetView { Widget navigationCard( BuildContext context, { + required String start, + required String end, required String destination, required List> modes, Map? navigation, @@ -1313,7 +1321,7 @@ class MessageBubble extends GetView { icon: const Icon(Icons.turn_left, color: Colors.white, size: 20), onPressed: () { - controller.openNavigation(); + controller.openNavigation(start, end, ""); }, ), ) diff --git a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt index 574237a89..13f8e3794 100644 --- a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt +++ b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt @@ -1186,7 +1186,7 @@ object AgentService : CoroutineScope { // 如果 playlist 中有有效的歌曲,开始播放 if (!start.isNullOrEmpty() && !end.isNullOrEmpty()) { Log.i(TAG, "启动导航服务 ${start} ${end}") - NavigationServiceHelper.startNavigation(context, startpos = start, endpos = end) + NavigationServiceHelper.startNavigation(context,"start", startpos = start, endpos = end) } else { Log.i(TAG, "启动导航服务失败") } diff --git a/local_plugins/amap_service/android/src/main/AndroidManifest.xml b/local_plugins/amap_service/android/src/main/AndroidManifest.xml index 019b115bd..624e09866 100644 --- a/local_plugins/amap_service/android/src/main/AndroidManifest.xml +++ b/local_plugins/amap_service/android/src/main/AndroidManifest.xml @@ -41,6 +41,9 @@ diff --git a/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/AmapServicePlugin.kt b/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/AmapServicePlugin.kt index c3e5da152..e28e7a484 100644 --- a/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/AmapServicePlugin.kt +++ b/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/AmapServicePlugin.kt @@ -42,7 +42,7 @@ class AmapServicePlugin: FlutterPlugin, MethodCallHandler,EventChannel.StreamHan val endpos = call.argument("endpos") val ntype = call.argument("ntype") if (startpos != null && endpos != null && ntype != null) { - NavigationServiceHelper.startNavigation(context,startpos,endpos,ntype) + NavigationServiceHelper.startNavigation(context,"start",startpos,endpos,ntype) result.success(null) } else { result.error("INVALID_ARGUMENT", "Missing 'song' map", null) @@ -50,13 +50,16 @@ class AmapServicePlugin: FlutterPlugin, MethodCallHandler,EventChannel.StreamHan } "open" -> { try { - NavigationServiceHelper.openNavigationUI() + val startpos = call.argument("startpos") + val endpos = call.argument("endpos") + val ntype = call.argument("ntype") + NavigationServiceHelper.openNavigationUI(startpos,endpos,ntype) }catch (e: Exception){ result.error("INVALID_ARGUMENT", "Try Exception ", e) } } "stop" -> { - NavigationServiceHelper.stopNavigation() + NavigationServiceHelper.startNavigation(context,"stop") result.success(null) } else -> { diff --git a/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationActivity.kt b/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationActivity.kt index 0c2f8e5f0..384990bff 100644 --- a/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationActivity.kt +++ b/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationActivity.kt @@ -1,11 +1,14 @@ package com.yunqiinnovation.amap_service +import android.content.Context import android.os.Bundle +import android.util.Log import androidx.appcompat.app.AppCompatActivity import com.amap.api.navi.AMapNavi import com.amap.api.navi.AMapNaviListener import com.amap.api.navi.AMapNaviView import com.amap.api.navi.AMapNaviViewListener +import com.amap.api.navi.enums.PathPlanningStrategy import com.amap.api.navi.model.AMapCalcRouteResult import com.amap.api.navi.model.AMapLaneInfo import com.amap.api.navi.model.AMapModelCross @@ -18,24 +21,35 @@ import com.amap.api.navi.model.AMapServiceAreaInfo import com.amap.api.navi.model.AimLessModeCongestionInfo import com.amap.api.navi.model.AimLessModeStat import com.amap.api.navi.model.NaviInfo +import com.amap.api.navi.model.NaviLatLng +import com.yunqiinnovation.amap_service.NavigationService.Companion.sharedNavi class NavigationActivity : AppCompatActivity(), AMapNaviListener, AMapNaviViewListener { private lateinit var naviView: AMapNaviView private var navi: AMapNavi? = null - + private lateinit var context: Context + private var startpos:String = ""; + private var endpos:String = ""; + private var ntype:String = ""; override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_navigation) - + context = this // 初始化导航视图 naviView = findViewById(R.id.navi_view) naviView.onCreate(savedInstanceState) naviView.setAMapNaviViewListener(this) + startpos = intent.getStringExtra("startpos").toString() + endpos = intent.getStringExtra("endpos").toString() + ntype = intent.getStringExtra("ntype").toString() + Log.i("NavigationActivity", "onCreate $startpos $endpos $ntype") navi = NavigationService.sharedNavi if (navi == null) { - finish() // 服务未启动,退出 - return + navi = AMapNavi.getInstance(context).apply { + setUseInnerVoice(true) + setBroadcastMode(1) + } } navi?.addAMapNaviListener(this); @@ -53,9 +67,13 @@ class NavigationActivity : AppCompatActivity(), AMapNaviListener, AMapNaviViewLi } override fun onDestroy() { - super.onDestroy() - naviView.onDestroy() + navi?.stopNavi() navi?.removeAMapNaviListener(this); + AMapNavi.destroy() + NavigationServiceHelper.startNavigation(context,"stop") + naviView.onDestroy() + super.onDestroy() + Log.i("NavigationActivity", "liwei------------------- onDestroy!") } override fun onInitNaviFailure() { @@ -63,6 +81,25 @@ class NavigationActivity : AppCompatActivity(), AMapNaviListener, AMapNaviViewLi } override fun onInitNaviSuccess() { + Log.i("NavigationActivity", "onInitNaviSuccess!") + // 起点 + val startParts: List = startpos.split(",") + val startLng = startParts[0].toDouble() + val startLat = startParts[1].toDouble() + + // 终点 + val endParts: List = endpos.split(",") + val endLng = endParts[0].toDouble() + val endLat = endParts[1].toDouble() + + val startList: MutableList = ArrayList() + val endList: MutableList = ArrayList() + startList.add(NaviLatLng(startLat, startLng)) + endList.add(NaviLatLng(endLat, endLng)) + val success = navi?.calculateDriveRoute(startList, endList, null, PathPlanningStrategy.DRIVING_MULTIPLE_ROUTES_DEFAULT); + if (!success!!) { + Log.e("NavigationActivity", "路径规划请求失败") + } // TODO("Not yet implemented") } @@ -167,6 +204,7 @@ class NavigationActivity : AppCompatActivity(), AMapNaviListener, AMapNaviViewLi } override fun onCalculateRouteSuccess(p0: IntArray?) { + navi?.startNavi(1); // TODO("Not yet implemented") } @@ -212,7 +250,7 @@ class NavigationActivity : AppCompatActivity(), AMapNaviListener, AMapNaviViewLi } override fun onNaviCancel() { - finish() + finishAndRemoveTask() // TODO("Not yet implemented") } diff --git a/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationService.kt b/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationService.kt index 7342a0c4d..dceab4f76 100644 --- a/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationService.kt +++ b/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationService.kt @@ -60,18 +60,27 @@ class NavigationService: Service(),AMapNaviListener { } override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { - try { - startpos = intent.getStringExtra("startpos").toString() - endpos = intent.getStringExtra("endpos").toString() - naviType = intent.getStringExtra("naviType"); - Log.w(TAG, "开始导航 startpos:$startpos endpos:$endpos naviType:$naviType") - if (startpos.isEmpty() || endpos.isEmpty()) { - Log.e(TAG, "Missing start or end position") + val command = intent.getStringExtra("command") ?: return START_NOT_STICKY + when (command) { + "start" ->{ + try { + startpos = intent.getStringExtra("startpos").toString() + endpos = intent.getStringExtra("endpos").toString() + naviType = intent.getStringExtra("naviType"); + Log.w(TAG, "开始导航 startpos:$startpos endpos:$endpos naviType:$naviType") + if (startpos.isEmpty() || endpos.isEmpty()) { + Log.e(TAG, "Missing start or end position") + return START_NOT_STICKY + } + initializeAMapNavi() + }catch (e: FileNotFoundException){ + Log.w("NavigationService", "Custom voice bin not found: ${e.message}") + } + } + "stop" -> { + stopNavigation() return START_NOT_STICKY } - initializeAMapNavi() - }catch (e: FileNotFoundException){ - Log.w("NavigationService", "Custom voice bin not found: ${e.message}") } return START_STICKY } @@ -148,6 +157,7 @@ class NavigationService: Service(),AMapNaviListener { if (sharedNavi != null) { sharedNavi?.stopNavi() sharedNavi?.removeAMapNaviListener(this) + sharedNavi = null } isRunning.set(false) stopSelf() @@ -271,14 +281,14 @@ class NavigationService: Service(),AMapNaviListener { String.format("%.1f 千米", remainingDistance / 1000.0) } val contentText = "$distanceText \n进入:$nextRoad" - val directionBitmapBase64 = bitmapToBase64(directionBitmap) - val naviInfoMap: Map = mapOf( - "currentRoad" to currentRoad, - "nextRoad" to nextRoad, - "distanceText" to distanceText, - "directionIcon" to (directionBitmapBase64 ?: "") - ) - NavigationServiceHelper.sendEvent("amap_update",naviInfoMap) +// val directionBitmapBase64 = bitmapToBase64(directionBitmap) +// val naviInfoMap: Map = mapOf( +// "currentRoad" to currentRoad, +// "nextRoad" to nextRoad, +// "distanceText" to distanceText, +// "directionIcon" to (directionBitmapBase64 ?: "") +// ) +// NavigationServiceHelper.sendEvent("amap_update",naviInfoMap) updateNotification(contentText, directionBitmap) Log.e(TAG, "onNaviInfoUpdate! $contentText") // TODO("Not yet implemented") @@ -340,7 +350,7 @@ class NavigationService: Service(),AMapNaviListener { override fun onCalculateRouteSuccess(p0: IntArray?) { Log.e(TAG, "onCalculateRouteSuccess! $p0") - sharedNavi?.startNavi(2); + sharedNavi?.startNavi(1); // TODO("Not yet implemented") } diff --git a/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationServiceHelper.kt b/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationServiceHelper.kt index 34575ed62..500e45bf7 100644 --- a/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationServiceHelper.kt +++ b/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationServiceHelper.kt @@ -29,24 +29,27 @@ object NavigationServiceHelper { context = appContext } //启动导航 - fun startNavigation(context: Context, startpos: String? = null, endpos: String? = null, ntype: String? = null) { - Log.i(TAG, "liwei------------------- startNavigation: $startpos $endpos $ntype") + fun startNavigation(context: Context,command:String, startpos: String? = null, endpos: String? = null, ntype: String? = null) { + Log.i(TAG, "liwei------------------- startNavigation: $command $startpos $endpos $ntype") val intent = Intent(context, NavigationService::class.java).apply { + putExtra("command", command) + startpos?.let { putExtra("startpos", it) } + endpos?.let { putExtra("endpos", it) } + ntype?.let { putExtra("ntype", it) } + } + ContextCompat.startForegroundService(context, intent) +// context.startForegroundService(intent) + } + + //打开导航页面 + fun openNavigationUI(startpos: String? = null, endpos: String? = null, ntype: String? = null) { + Log.i(TAG, "liwei------------------- openNavigationUI: $startpos $endpos $ntype") + val intent = Intent(context, NavigationActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) putExtra("startpos", startpos) putExtra("endpos", endpos) putExtra("ntype", ntype) } - context.startForegroundService(intent) - } - //停止导航 - fun stopNavigation() { - val intent = Intent(context, NavigationService::class.java) - context.stopService(intent) - } - //打开导航页面 - fun openNavigationUI() { - val intent = Intent(context, NavigationActivity::class.java) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(intent) } diff --git a/local_plugins/amap_service/lib/amap_service.dart b/local_plugins/amap_service/lib/amap_service.dart index 29bc9d921..b90fd5434 100644 --- a/local_plugins/amap_service/lib/amap_service.dart +++ b/local_plugins/amap_service/lib/amap_service.dart @@ -98,8 +98,12 @@ class AmapService { await _methodChannel.invokeMethod('start'); } - Future open() async { - await _methodChannel.invokeMethod('open'); + Future open(String start, String end, String ntype) async { + await _methodChannel.invokeMethod('open', { + 'startpos': start, + "endpos": end, + "ntype": ntype, + }); } Future stop() async { diff --git a/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/SystemFunctionHandler.kt b/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/SystemFunctionHandler.kt index b491eb1bd..d56f3d77d 100644 --- a/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/SystemFunctionHandler.kt +++ b/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/SystemFunctionHandler.kt @@ -29,6 +29,7 @@ import android.content.ContentUris import androidx.core.content.ContextCompat import android.app.ActivityManager import android.app.Application +import android.content.ComponentName import android.os.Process /** * 系统功能处理器 - 负责调用系统API执行各种功能以及注册系统功能 @@ -77,7 +78,9 @@ class SystemFunctionHandler(private val context: Context) { // 注册打开录音机功能 registerOpenRecorderFunction(client) - + + // 注册关闭导航服务功能 + registerStopNavigationFunction(client) Log.d(TAG, "所有系统功能注册完成") } catch (e: Exception) { Log.e(TAG, "注册系统功能失败: ${e.message}", e) @@ -443,7 +446,29 @@ class SystemFunctionHandler(private val context: Context) { ) Log.d(TAG, "已注册打开录音机功能") } - + /** + * 注册获取当前时间函数 + */ + private fun registerStopNavigationFunction(client: MCPClient) { + client.registerLocalFunction( + "stop_navigation", + "结束当前导航服务", + JSONObject(""" + { + "type": "object", + "properties": {}, + "required": [] + } + """), + object : FunctionHandler { + override suspend fun handle(arguments: Map): String { + val result = stopNavigation() + return "{\"result\": \"${result.message}\"}" + } + } + ) + Log.d(TAG, "已注册获取当前时间功能") + } /** * 控制媒体播放 * @param action 操作类型:"play", "pause", "previous", "next" @@ -1270,7 +1295,31 @@ class SystemFunctionHandler(private val context: Context) { false } } - + + + /** + * 停止当前导航 + * @return 操作结果 + */ + fun stopNavigation():Result{ + Log.d(TAG, "结束当前导航服务") + try { +// val intent = Intent() +// intent.component = ComponentName("com.example.plugin", "com.example.plugin.MyBackgroundService") +// stopService(intent) + return Result( + success = true, + message = "当前导航服务已结束" + ) + } catch (e: Exception) { + Log.e(TAG, "结束当前导航服务失败: ${e.message}", e) + return Result( + success = false, + message = "结束当前导航服务失败: ${e.message}" + ) + } + } + /** * 操作结果数据类 */