|
|
|
@ -1884,7 +1884,7 @@ object AgentService : CoroutineScope { |
|
|
|
|
|
|
|
metadata[toolname] = meta // 现在可以赋值 |
|
|
|
metadata["notreply"] = notreply // 现在可以赋值 |
|
|
|
val metaStr = JSONObject(metadata as Map<*, *>).toString() |
|
|
|
|
|
|
|
// Log.d(TAG, "mcp调用结果: $metaStr") |
|
|
|
if (meta.has("card_music")) { //音乐卡片 |
|
|
|
val cardMusic = meta.getJSONObject("card_music") |
|
|
|
@ -1967,13 +1967,24 @@ object AgentService : CoroutineScope { |
|
|
|
}else if (meta.has("card_navigation")) { //导航服务 |
|
|
|
val cardNavigation = meta.getJSONObject("card_navigation") |
|
|
|
val start = cardNavigation.optString("start", "") |
|
|
|
val end = cardNavigation.optString("end", "") |
|
|
|
processNavigation(start, end); |
|
|
|
val destination = cardNavigation.optString("destination", "") |
|
|
|
val end_longitude = cardNavigation.optString("end_longitude", "") |
|
|
|
val end_latitude = cardNavigation.optString("end_latitude", "") |
|
|
|
// final start = card_navigation["start"] 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; |
|
|
|
var isinternal = processNavigation(start, destination,end_latitude,end_longitude,"driving"); |
|
|
|
metadata["isinternal"] = isinternal // 是否是内部导航 |
|
|
|
}else if (toolname == "map_weather") { //导航服务 |
|
|
|
iscard = true |
|
|
|
}else if (toolname == "maps_weather") { //导航服务 |
|
|
|
iscard = true |
|
|
|
} |
|
|
|
val metaStr = JSONObject(metadata as Map<*, *>).toString() |
|
|
|
return mapOf("meta" to metaStr, "broadcast" to broadcast, "notreply" to notreply,"iscard" to iscard); |
|
|
|
} |
|
|
|
} catch (e: Exception) { |
|
|
|
@ -2055,25 +2066,254 @@ object AgentService : CoroutineScope { |
|
|
|
} |
|
|
|
/** |
|
|
|
* 处理导航 |
|
|
|
* 将ai返回的音乐连接 在后台启动播放 |
|
|
|
* @param musicUrl 图片文件路径 |
|
|
|
* @param name 歌曲名称,默认为空 |
|
|
|
* @param singer 歌手,默认为false |
|
|
|
* 启动导航服务到指定目的地 |
|
|
|
* @param start 起点地址 |
|
|
|
* @param destination 目的地地址 |
|
|
|
* @param endlatitude 目的地纬度 |
|
|
|
* @param endlongitude 目的地经度 |
|
|
|
* @param mode 导航模式:driving(驾车)、transit(公交)、walking(步行)、cycling(骑行) |
|
|
|
* @return 是否成功开始处理 |
|
|
|
*/ |
|
|
|
fun processNavigation(start: String, end: String) { |
|
|
|
if (navigationMode == "internal_gaode"){ |
|
|
|
// 如果 playlist 中有有效的歌曲,开始播放 |
|
|
|
if (!start.isNullOrEmpty() && !end.isNullOrEmpty()) { |
|
|
|
NavigationServiceHelper.startNavigation( |
|
|
|
context, |
|
|
|
"start", |
|
|
|
startpos = start, |
|
|
|
endpos = end |
|
|
|
) |
|
|
|
fun processNavigation(start: String, destination: String, |
|
|
|
endlatitude: String, endlongitude: String, mode: String):Boolean { |
|
|
|
Log.d(TAG, "processNavigation: $start -> $destination ($endlongitude,$endlatitude,), mode: $mode") |
|
|
|
|
|
|
|
if (destination.isEmpty()) { |
|
|
|
Log.i(TAG, "启动导航服务失败:目的地为空") |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// 获取导航模式配置,默认为自动选择 |
|
|
|
val configNavigationMode = navigationMode.ifEmpty { "external_auto" } |
|
|
|
Log.d(TAG, "导航模式配置: $configNavigationMode") |
|
|
|
|
|
|
|
when (configNavigationMode) { |
|
|
|
"internal_gaode" -> { |
|
|
|
// 使用内置高德导航 |
|
|
|
navigateWithInternalGaode(start, destination, endlatitude, endlongitude, mode) |
|
|
|
return true |
|
|
|
} |
|
|
|
"external_baidu" -> { |
|
|
|
// 使用外部百度地图 |
|
|
|
navigateWithBaiduMap(destination, endlatitude, endlongitude, mode) |
|
|
|
return false |
|
|
|
} |
|
|
|
"external_gaode" -> { |
|
|
|
// 使用外部高德地图 |
|
|
|
navigateWithGaodeMap(destination, endlatitude, endlongitude, mode) |
|
|
|
return false |
|
|
|
} |
|
|
|
"external_google" -> { |
|
|
|
// 使用外部谷歌地图 |
|
|
|
navigateWithGoogleMap(destination, mode) |
|
|
|
return false |
|
|
|
} |
|
|
|
else -> { |
|
|
|
// 自动选择导航应用,优先级:百度 > 高德 > 谷歌 > 内置高德 |
|
|
|
return autoSelectNavigation(start, destination, endlatitude, endlongitude, mode) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 使用内置高德导航 |
|
|
|
*/ |
|
|
|
private fun navigateWithInternalGaode(start: String, destination: String, |
|
|
|
endlatitude: String, endlongitude: String, mode: String) { |
|
|
|
try { |
|
|
|
val endpos = if (endlatitude.isNotEmpty() && endlongitude.isNotEmpty()) { |
|
|
|
"$endlongitude,$endlatitude" |
|
|
|
} else { |
|
|
|
Log.i(TAG, "启动导航服务失败") |
|
|
|
destination |
|
|
|
} |
|
|
|
|
|
|
|
NavigationServiceHelper.startNavigation( |
|
|
|
context, |
|
|
|
"start", |
|
|
|
startpos = start, |
|
|
|
endpos = "$endlongitude,$endlatitude" |
|
|
|
) |
|
|
|
Log.i(TAG, "启动内置高德导航服务成功") |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.e(TAG, "启动内置高德导航失败: ${e.message}", e) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 使用百度地图导航 |
|
|
|
*/ |
|
|
|
private fun navigateWithBaiduMap(destination: String, endlatitude: String, |
|
|
|
endlongitude: String, mode: String) { |
|
|
|
try { |
|
|
|
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0) |
|
|
|
val src = packageInfo.packageName |
|
|
|
|
|
|
|
// 百度地图导航模式映射 |
|
|
|
val baiduMode = when (mode) { |
|
|
|
"transit" -> "transit" |
|
|
|
"walking" -> "walking" |
|
|
|
"cycling" -> "riding" |
|
|
|
else -> "driving" |
|
|
|
} |
|
|
|
|
|
|
|
// 构建目的地参数 |
|
|
|
val destinationParam = if (endlatitude.isNotEmpty() && endlongitude.isNotEmpty()) { |
|
|
|
"name:$destination|latlng:$endlatitude,$endlongitude" |
|
|
|
} else { |
|
|
|
destination |
|
|
|
} |
|
|
|
|
|
|
|
val uri = android.net.Uri.parse("baidumap://map/direction?" + |
|
|
|
"destination=$destinationParam&" + |
|
|
|
"coord_type=gcj02&" + |
|
|
|
"mode=$baiduMode&" + |
|
|
|
"src=$src") |
|
|
|
|
|
|
|
val intent = Intent(Intent.ACTION_VIEW, uri).apply { |
|
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
|
} |
|
|
|
|
|
|
|
if (isAppInstalled("com.baidu.BaiduMap")) { |
|
|
|
context.startActivity(intent) |
|
|
|
Log.i(TAG, "已启动百度地图导航") |
|
|
|
} else { |
|
|
|
Log.w(TAG, "百度地图未安装") |
|
|
|
throw Exception("百度地图未安装") |
|
|
|
} |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.e(TAG, "启动百度地图失败: ${e.message}", e) |
|
|
|
// 回退到其他导航方式 |
|
|
|
navigateWithGaodeMap(destination, endlatitude, endlongitude, mode) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 使用高德地图导航 |
|
|
|
*/ |
|
|
|
private fun navigateWithGaodeMap(destination: String, endlatitude: String, |
|
|
|
endlongitude: String, mode: String) { |
|
|
|
try { |
|
|
|
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0) |
|
|
|
val src = packageInfo.packageName |
|
|
|
|
|
|
|
// 高德地图导航模式映射 |
|
|
|
val gaodeMode = when (mode) { |
|
|
|
"transit" -> "1" |
|
|
|
"walking" -> "2" |
|
|
|
"cycling" -> "3" |
|
|
|
else -> "0" |
|
|
|
} |
|
|
|
|
|
|
|
val uriBuilder = StringBuilder("androidamap://route/plan?") |
|
|
|
if (endlatitude.isNotEmpty() && endlongitude.isNotEmpty()) { |
|
|
|
uriBuilder.append("dlat=$endlatitude&") |
|
|
|
uriBuilder.append("dlon=$endlongitude&") |
|
|
|
} |
|
|
|
uriBuilder.append("dname=$destination&") |
|
|
|
uriBuilder.append("dev=0&") |
|
|
|
uriBuilder.append("t=$gaodeMode&") |
|
|
|
uriBuilder.append("sourceApplication=$src") |
|
|
|
|
|
|
|
val uri = android.net.Uri.parse(uriBuilder.toString()) |
|
|
|
val intent = Intent(Intent.ACTION_VIEW, uri).apply { |
|
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
|
} |
|
|
|
|
|
|
|
if (isAppInstalled("com.autonavi.minimap")) { |
|
|
|
context.startActivity(intent) |
|
|
|
Log.i(TAG, "已启动高德地图导航") |
|
|
|
} else { |
|
|
|
Log.w(TAG, "高德地图未安装") |
|
|
|
throw Exception("高德地图未安装") |
|
|
|
} |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.e(TAG, "启动高德地图失败: ${e.message}", e) |
|
|
|
// 回退到其他导航方式 |
|
|
|
navigateWithGoogleMap(destination, mode) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 使用谷歌地图导航 |
|
|
|
*/ |
|
|
|
private fun navigateWithGoogleMap(destination: String, mode: String) { |
|
|
|
try { |
|
|
|
// 谷歌地图导航模式映射 |
|
|
|
val googleMode = when (mode) { |
|
|
|
"transit" -> "transit" |
|
|
|
"walking" -> "walking" |
|
|
|
"cycling" -> "bicycling" |
|
|
|
else -> "driving" |
|
|
|
} |
|
|
|
|
|
|
|
// 尝试使用Google Maps应用 |
|
|
|
val appUri = android.net.Uri.parse("comgooglemaps://?saddr=Current+Location&daddr=$destination&directionsmode=$googleMode") |
|
|
|
val appIntent = Intent(Intent.ACTION_VIEW, appUri).apply { |
|
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
|
} |
|
|
|
|
|
|
|
if (isAppInstalled("com.google.android.apps.maps")) { |
|
|
|
context.startActivity(appIntent) |
|
|
|
Log.i(TAG, "已启动谷歌地图导航") |
|
|
|
} else { |
|
|
|
// 回退到网页版 |
|
|
|
val webUri = android.net.Uri.parse("https://www.google.com/maps/dir/?api=1&origin=Current+Location&destination=$destination&travelmode=$googleMode") |
|
|
|
val webIntent = Intent(Intent.ACTION_VIEW, webUri).apply { |
|
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
|
} |
|
|
|
context.startActivity(webIntent) |
|
|
|
Log.i(TAG, "已启动谷歌地图网页版导航") |
|
|
|
} |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.e(TAG, "启动谷歌地图失败: ${e.message}", e) |
|
|
|
// 最后回退到内置导航 |
|
|
|
navigateWithInternalGaode("", destination, "", "", mode) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 自动选择导航应用 |
|
|
|
*/ |
|
|
|
private fun autoSelectNavigation(start: String, destination: String, |
|
|
|
endlatitude: String, endlongitude: String, mode: String):Boolean { |
|
|
|
Log.d(TAG, "自动选择导航应用") |
|
|
|
|
|
|
|
// 1. 优先尝试百度地图 |
|
|
|
if (isAppInstalled("com.baidu.BaiduMap")) { |
|
|
|
Log.d(TAG, "自动选择:使用百度地图") |
|
|
|
navigateWithBaiduMap(destination, endlatitude, endlongitude, mode) |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// 2. 其次尝试高德地图 |
|
|
|
if (isAppInstalled("com.autonavi.minimap")) { |
|
|
|
Log.d(TAG, "自动选择:使用高德地图") |
|
|
|
navigateWithGaodeMap(destination, endlatitude, endlongitude, mode) |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// 3. 然后尝试谷歌地图 |
|
|
|
if (isAppInstalled("com.google.android.apps.maps")) { |
|
|
|
Log.d(TAG, "自动选择:使用谷歌地图") |
|
|
|
navigateWithGoogleMap(destination, mode) |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// 4. 最后使用内置高德导航 |
|
|
|
Log.d(TAG, "自动选择:使用内置高德导航") |
|
|
|
navigateWithInternalGaode(start, destination, endlatitude, endlongitude, mode) |
|
|
|
return true |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 检查应用是否已安装 |
|
|
|
*/ |
|
|
|
private fun isAppInstalled(packageName: String): Boolean { |
|
|
|
return try { |
|
|
|
context.packageManager.getPackageInfo(packageName, 0) |
|
|
|
true |
|
|
|
} catch (e: Exception) { |
|
|
|
false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|