|
|
@ -36,6 +36,11 @@ import java.io.IOException |
|
|
import java.text.SimpleDateFormat |
|
|
import java.text.SimpleDateFormat |
|
|
import java.util.Locale |
|
|
import java.util.Locale |
|
|
import java.util.Date |
|
|
import java.util.Date |
|
|
|
|
|
// 添加后台启动相关导入 |
|
|
|
|
|
import android.app.PendingIntent |
|
|
|
|
|
import android.app.NotificationManager |
|
|
|
|
|
import android.app.NotificationChannel |
|
|
|
|
|
import androidx.core.app.NotificationCompat |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
@ -1015,7 +1020,7 @@ object AgentService : CoroutineScope { |
|
|
if (reply) { |
|
|
if (reply) { |
|
|
sendEvent("assistant_response", responseData) |
|
|
sendEvent("assistant_response", responseData) |
|
|
} |
|
|
} |
|
|
|
|
|
Log.d(TAG, "liwei--------------- AI Call onComplete:$response") |
|
|
if (response.isNotEmpty()) { |
|
|
if (response.isNotEmpty()) { |
|
|
// 添加AI回复到历史记录 |
|
|
// 添加AI回复到历史记录 |
|
|
addToHistoryMessages(createAssistantMessage(response)) |
|
|
addToHistoryMessages(createAssistantMessage(response)) |
|
|
@ -1081,19 +1086,23 @@ object AgentService : CoroutineScope { |
|
|
audioPlayer?.stopAudio() |
|
|
audioPlayer?.stopAudio() |
|
|
val name = functionCall.get("name") as String; |
|
|
val name = functionCall.get("name") as String; |
|
|
val resultmap = autoHandleFcunCallResult(name, functionCallResult); |
|
|
val resultmap = autoHandleFcunCallResult(name, functionCallResult); |
|
|
aiMetadata = resultmap["meta"] as String; |
|
|
|
|
|
broadcast = resultmap["broadcast"] as Boolean; |
|
|
broadcast = resultmap["broadcast"] as Boolean; |
|
|
reply = !(resultmap["notreply"] as Boolean); |
|
|
reply = !(resultmap["notreply"] as Boolean); |
|
|
iscard = resultmap["iscard"] as Boolean; |
|
|
iscard = resultmap["iscard"] as Boolean; |
|
|
if (iscard){ |
|
|
if (iscard){ |
|
|
sendEvent( |
|
|
aiMetadata = resultmap["meta"] as String; |
|
|
"function_call_result", mapOf( |
|
|
|
|
|
"function_call" to functionCall.toString(), |
|
|
|
|
|
"result" to functionCallResult.toString(), |
|
|
|
|
|
"meta" to aiMetadata, |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
sendEvent( |
|
|
|
|
|
"function_call_result", mapOf( |
|
|
|
|
|
"function_call" to functionCall.toString(), |
|
|
|
|
|
"result" to functionCallResult.toString(), |
|
|
|
|
|
"meta" to aiMetadata, |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
Log.e( |
|
|
|
|
|
TAG, |
|
|
|
|
|
"liwei--------------- AI Call onFunctionCallResult broadcast:$broadcast reply:$reply iscard:$iscard" |
|
|
|
|
|
) |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
Log.e( |
|
|
Log.e( |
|
|
TAG, |
|
|
TAG, |
|
|
@ -1859,13 +1868,13 @@ object AgentService : CoroutineScope { |
|
|
toolname: String, |
|
|
toolname: String, |
|
|
functionCallResult: JSONObject |
|
|
functionCallResult: JSONObject |
|
|
): Map<String, Any> { |
|
|
): Map<String, Any> { |
|
|
println("协议工具返回数据 检查是否存在卡片! functionCallResult: ${functionCallResult}") |
|
|
// println("协议工具返回数据 检查是否存在卡片! functionCallResult: ${functionCallResult}") |
|
|
try { |
|
|
try { |
|
|
val contentStr = functionCallResult.optString("context") |
|
|
val contentStr = functionCallResult.optString("context") |
|
|
println("协议工具返回数据 检查是否存在卡片! context: ${contentStr}") |
|
|
// println("协议工具返回数据 检查是否存在卡片! context: ${contentStr}") |
|
|
val content = JSONObject(contentStr) |
|
|
val content = JSONObject(contentStr) |
|
|
val textStr = content.optString("text") |
|
|
val textStr = content.optString("text") |
|
|
println("协议工具返回数据 检查是否存在卡片! textStr: ${textStr}") |
|
|
// println("协议工具返回数据 检查是否存在卡片! textStr: ${textStr}") |
|
|
val metadata: MutableMap<String, Any> = mutableMapOf() |
|
|
val metadata: MutableMap<String, Any> = mutableMapOf() |
|
|
var broadcast = true; |
|
|
var broadcast = true; |
|
|
var notreply = false; |
|
|
var notreply = false; |
|
|
@ -2170,12 +2179,25 @@ object AgentService : CoroutineScope { |
|
|
"src=$src") |
|
|
"src=$src") |
|
|
|
|
|
|
|
|
val intent = Intent(Intent.ACTION_VIEW, uri).apply { |
|
|
val intent = Intent(Intent.ACTION_VIEW, uri).apply { |
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK or |
|
|
|
|
|
Intent.FLAG_ACTIVITY_CLEAR_TOP or |
|
|
|
|
|
Intent.FLAG_ACTIVITY_SINGLE_TOP |
|
|
|
|
|
// 添加包名确保启动正确的应用 |
|
|
|
|
|
setPackage("com.baidu.BaiduMap") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (isAppInstalled("com.baidu.BaiduMap")) { |
|
|
if (isAppInstalled("com.baidu.BaiduMap")) { |
|
|
context.startActivity(intent) |
|
|
try { |
|
|
Log.i(TAG, "已启动百度地图导航") |
|
|
context.startActivity(intent) |
|
|
|
|
|
Log.i(TAG, "已启动百度地图导航") |
|
|
|
|
|
} catch (e: SecurityException) { |
|
|
|
|
|
// Android 10+ 后台启动限制,尝试使用 PendingIntent |
|
|
|
|
|
Log.w(TAG, "后台启动受限,尝试使用通知启动百度地图: ${e.message}") |
|
|
|
|
|
startActivityWithPendingIntent(intent, "百度地图导航") |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(TAG, "启动百度地图失败: ${e.message}", e) |
|
|
|
|
|
throw e |
|
|
|
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
Log.w(TAG, "百度地图未安装") |
|
|
Log.w(TAG, "百度地图未安装") |
|
|
throw Exception("百度地图未安装") |
|
|
throw Exception("百度地图未安装") |
|
|
@ -2216,12 +2238,25 @@ object AgentService : CoroutineScope { |
|
|
|
|
|
|
|
|
val uri = android.net.Uri.parse(uriBuilder.toString()) |
|
|
val uri = android.net.Uri.parse(uriBuilder.toString()) |
|
|
val intent = Intent(Intent.ACTION_VIEW, uri).apply { |
|
|
val intent = Intent(Intent.ACTION_VIEW, uri).apply { |
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK or |
|
|
|
|
|
Intent.FLAG_ACTIVITY_CLEAR_TOP or |
|
|
|
|
|
Intent.FLAG_ACTIVITY_SINGLE_TOP |
|
|
|
|
|
// 添加包名确保启动正确的应用 |
|
|
|
|
|
setPackage("com.autonavi.minimap") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (isAppInstalled("com.autonavi.minimap")) { |
|
|
if (isAppInstalled("com.autonavi.minimap")) { |
|
|
context.startActivity(intent) |
|
|
try { |
|
|
Log.i(TAG, "已启动高德地图导航") |
|
|
context.startActivity(intent) |
|
|
|
|
|
Log.i(TAG, "已启动高德地图导航") |
|
|
|
|
|
} catch (e: SecurityException) { |
|
|
|
|
|
// Android 10+ 后台启动限制,尝试使用 PendingIntent |
|
|
|
|
|
Log.w(TAG, "后台启动受限,尝试使用通知启动高德地图: ${e.message}") |
|
|
|
|
|
startActivityWithPendingIntent(intent, "高德地图导航") |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(TAG, "启动高德地图失败: ${e.message}", e) |
|
|
|
|
|
throw e |
|
|
|
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
Log.w(TAG, "高德地图未安装") |
|
|
Log.w(TAG, "高德地图未安装") |
|
|
throw Exception("高德地图未安装") |
|
|
throw Exception("高德地图未安装") |
|
|
@ -2249,20 +2284,44 @@ object AgentService : CoroutineScope { |
|
|
// 尝试使用Google Maps应用 |
|
|
// 尝试使用Google Maps应用 |
|
|
val appUri = android.net.Uri.parse("comgooglemaps://?saddr=Current+Location&daddr=$destination&directionsmode=$googleMode") |
|
|
val appUri = android.net.Uri.parse("comgooglemaps://?saddr=Current+Location&daddr=$destination&directionsmode=$googleMode") |
|
|
val appIntent = Intent(Intent.ACTION_VIEW, appUri).apply { |
|
|
val appIntent = Intent(Intent.ACTION_VIEW, appUri).apply { |
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK or |
|
|
|
|
|
Intent.FLAG_ACTIVITY_CLEAR_TOP or |
|
|
|
|
|
Intent.FLAG_ACTIVITY_SINGLE_TOP |
|
|
|
|
|
// 添加包名确保启动正确的应用 |
|
|
|
|
|
setPackage("com.google.android.apps.maps") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (isAppInstalled("com.google.android.apps.maps")) { |
|
|
if (isAppInstalled("com.google.android.apps.maps")) { |
|
|
context.startActivity(appIntent) |
|
|
try { |
|
|
Log.i(TAG, "已启动谷歌地图导航") |
|
|
context.startActivity(appIntent) |
|
|
|
|
|
Log.i(TAG, "已启动谷歌地图导航") |
|
|
|
|
|
} catch (e: SecurityException) { |
|
|
|
|
|
// Android 10+ 后台启动限制,尝试使用 PendingIntent |
|
|
|
|
|
Log.w(TAG, "后台启动受限,尝试使用通知启动谷歌地图: ${e.message}") |
|
|
|
|
|
startActivityWithPendingIntent(appIntent, "谷歌地图导航") |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(TAG, "启动谷歌地图失败: ${e.message}", e) |
|
|
|
|
|
throw e |
|
|
|
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
// 回退到网页版 |
|
|
// 回退到网页版 |
|
|
val webUri = android.net.Uri.parse("https://www.google.com/maps/dir/?api=1&origin=Current+Location&destination=$destination&travelmode=$googleMode") |
|
|
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 { |
|
|
val webIntent = Intent(Intent.ACTION_VIEW, webUri).apply { |
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK or |
|
|
|
|
|
Intent.FLAG_ACTIVITY_CLEAR_TOP or |
|
|
|
|
|
Intent.FLAG_ACTIVITY_SINGLE_TOP |
|
|
|
|
|
} |
|
|
|
|
|
try { |
|
|
|
|
|
context.startActivity(webIntent) |
|
|
|
|
|
Log.i(TAG, "已启动谷歌地图网页版导航") |
|
|
|
|
|
} catch (e: SecurityException) { |
|
|
|
|
|
// Android 10+ 后台启动限制,尝试使用 PendingIntent |
|
|
|
|
|
Log.w(TAG, "后台启动受限,尝试使用通知启动谷歌地图网页版: ${e.message}") |
|
|
|
|
|
startActivityWithPendingIntent(webIntent, "谷歌地图网页版导航") |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(TAG, "启动谷歌地图网页版失败: ${e.message}", e) |
|
|
|
|
|
throw e |
|
|
} |
|
|
} |
|
|
context.startActivity(webIntent) |
|
|
|
|
|
Log.i(TAG, "已启动谷歌地图网页版导航") |
|
|
|
|
|
} |
|
|
} |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
Log.e(TAG, "启动谷歌地图失败: ${e.message}", e) |
|
|
Log.e(TAG, "启动谷歌地图失败: ${e.message}", e) |
|
|
@ -2305,6 +2364,54 @@ object AgentService : CoroutineScope { |
|
|
return true |
|
|
return true |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 使用 PendingIntent 启动 Activity(适用于后台启动场景) |
|
|
|
|
|
*/ |
|
|
|
|
|
private fun startActivityWithPendingIntent(intent: android.content.Intent, description: String) { |
|
|
|
|
|
try { |
|
|
|
|
|
val pendingIntent = PendingIntent.getActivity( |
|
|
|
|
|
context, |
|
|
|
|
|
System.currentTimeMillis().toInt(), // 使用时间戳作为唯一ID |
|
|
|
|
|
intent, |
|
|
|
|
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// 创建通知渠道(Android 8.0+) |
|
|
|
|
|
val channelId = "navigation_channel" |
|
|
|
|
|
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager |
|
|
|
|
|
|
|
|
|
|
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { |
|
|
|
|
|
val channel = NotificationChannel( |
|
|
|
|
|
channelId, |
|
|
|
|
|
"导航服务", |
|
|
|
|
|
NotificationManager.IMPORTANCE_HIGH |
|
|
|
|
|
).apply { |
|
|
|
|
|
this.description = "用于启动导航应用" |
|
|
|
|
|
enableVibration(true) |
|
|
|
|
|
enableLights(true) |
|
|
|
|
|
} |
|
|
|
|
|
notificationManager.createNotificationChannel(channel) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 创建通知 |
|
|
|
|
|
val notification = NotificationCompat.Builder(context, channelId) |
|
|
|
|
|
.setSmallIcon(android.R.drawable.ic_dialog_map) |
|
|
|
|
|
.setContentTitle("启动导航") |
|
|
|
|
|
.setContentText("点击启动$description") |
|
|
|
|
|
.setContentIntent(pendingIntent) |
|
|
|
|
|
.setAutoCancel(true) |
|
|
|
|
|
.setPriority(NotificationCompat.PRIORITY_HIGH) |
|
|
|
|
|
.setDefaults(NotificationCompat.DEFAULT_ALL) |
|
|
|
|
|
.build() |
|
|
|
|
|
|
|
|
|
|
|
notificationManager.notify(1001, notification) |
|
|
|
|
|
Log.i(TAG, "已通过通知启动$description") |
|
|
|
|
|
|
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(TAG, "PendingIntent 启动失败: ${e.message}", e) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 检查应用是否已安装 |
|
|
* 检查应用是否已安装 |
|
|
*/ |
|
|
*/ |
|
|
|