|
|
|
@ -102,18 +102,26 @@ class VoiceInteractionService : Service() { |
|
|
|
|
|
|
|
// 初始化组件 |
|
|
|
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager |
|
|
|
Log.d(TAG, "AudioManager初始化完成") |
|
|
|
|
|
|
|
initServices() |
|
|
|
initMediaSession() |
|
|
|
registerMediaButtonReceiver() |
|
|
|
|
|
|
|
// 设置为媒体播放状态 |
|
|
|
setPlaybackState(PlaybackStateCompat.STATE_PLAYING) |
|
|
|
Log.d(TAG, "设置播放状态为PLAYING") |
|
|
|
|
|
|
|
// 启动监控和前台服务 |
|
|
|
startMonitoring() |
|
|
|
startForegroundServiceWithNotification() |
|
|
|
|
|
|
|
Log.d(TAG, "VoiceInteractionService 初始化完成,等待蓝牙按键事件...") |
|
|
|
|
|
|
|
// 延迟3秒后测试按键处理功能 |
|
|
|
// Handler(Looper.getMainLooper()).postDelayed({ |
|
|
|
// testMediaButtonEvent() |
|
|
|
// }, 3000) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
@ -163,6 +171,7 @@ class VoiceInteractionService : Service() { |
|
|
|
* 初始化 MediaSession |
|
|
|
*/ |
|
|
|
private fun initMediaSession() { |
|
|
|
Log.d(TAG, "开始初始化MediaSession") |
|
|
|
mediaSession = MediaSessionCompat(applicationContext, "VoiceServiceSession") |
|
|
|
|
|
|
|
// 设置标志和状态 |
|
|
|
@ -170,10 +179,13 @@ class VoiceInteractionService : Service() { |
|
|
|
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or |
|
|
|
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS |
|
|
|
) |
|
|
|
Log.d(TAG, "MediaSession标志设置完成") |
|
|
|
|
|
|
|
// 设置回调 |
|
|
|
mediaSession.setCallback(object : MediaSessionCompat.Callback() { |
|
|
|
override fun onMediaButtonEvent(mediaButtonEvent: Intent): Boolean { |
|
|
|
Log.d(TAG, "收到媒体按钮事件: $mediaButtonEvent") |
|
|
|
|
|
|
|
val keyEvent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { |
|
|
|
mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT, KeyEvent::class.java) |
|
|
|
} else { |
|
|
|
@ -181,43 +193,75 @@ class VoiceInteractionService : Service() { |
|
|
|
mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT) as? KeyEvent |
|
|
|
} |
|
|
|
|
|
|
|
if (keyEvent != null && keyEvent.action == KeyEvent.ACTION_DOWN) { |
|
|
|
when (keyEvent.keyCode) { |
|
|
|
KeyEvent.KEYCODE_MEDIA_PLAY, |
|
|
|
KeyEvent.KEYCODE_MEDIA_PAUSE, |
|
|
|
KeyEvent.KEYCODE_HEADSETHOOK, |
|
|
|
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> { |
|
|
|
// 检测双击 |
|
|
|
val currentTime = System.currentTimeMillis() |
|
|
|
val timeDiff = currentTime - lastKeyEventTime |
|
|
|
|
|
|
|
if (timeDiff < 500) { // 500毫秒内的按键视为连续按键 |
|
|
|
keyEventCount++ |
|
|
|
if (keyEventCount == 1) { // 这是第二次按键,即双击 |
|
|
|
handleDoubleClick() |
|
|
|
if (keyEvent != null) { |
|
|
|
Log.d(TAG, "解析到按键事件: action=${keyEvent.action}, keyCode=${keyEvent.keyCode}") |
|
|
|
|
|
|
|
if (keyEvent.action == KeyEvent.ACTION_DOWN) { |
|
|
|
when (keyEvent.keyCode) { |
|
|
|
KeyEvent.KEYCODE_MEDIA_PLAY -> { |
|
|
|
Log.d(TAG, "检测到MEDIA_PLAY按键") |
|
|
|
handleDoubleClick() |
|
|
|
return true |
|
|
|
} |
|
|
|
KeyEvent.KEYCODE_MEDIA_PAUSE -> { |
|
|
|
Log.d(TAG, "检测到MEDIA_PAUSE按键") |
|
|
|
handleDoubleClick() |
|
|
|
return true |
|
|
|
} |
|
|
|
KeyEvent.KEYCODE_HEADSETHOOK -> { |
|
|
|
Log.d(TAG, "检测到HEADSETHOOK按键") |
|
|
|
// 检测双击 |
|
|
|
val currentTime = System.currentTimeMillis() |
|
|
|
val timeDiff = currentTime - lastKeyEventTime |
|
|
|
|
|
|
|
Log.d(TAG, "按键时间差: $timeDiff ms, 当前计数: $keyEventCount") |
|
|
|
|
|
|
|
if (timeDiff < 500) { // 500毫秒内的按键视为连续按键 |
|
|
|
keyEventCount++ |
|
|
|
Log.d(TAG, "连续按键,计数增加到: $keyEventCount") |
|
|
|
if (keyEventCount == 1) { // 这是第二次按键,即双击 |
|
|
|
Log.d(TAG, "检测到双击,执行处理") |
|
|
|
handleDoubleClick() |
|
|
|
keyEventCount = 0 |
|
|
|
return true |
|
|
|
} |
|
|
|
} else { |
|
|
|
Log.d(TAG, "非连续按键,重置计数") |
|
|
|
keyEventCount = 0 |
|
|
|
return true |
|
|
|
} |
|
|
|
} else { |
|
|
|
keyEventCount = 0 |
|
|
|
lastKeyEventTime = currentTime |
|
|
|
|
|
|
|
// 单击也处理 |
|
|
|
Log.d(TAG, "单击也处理") |
|
|
|
handleDoubleClick() |
|
|
|
return true |
|
|
|
} |
|
|
|
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> { |
|
|
|
Log.d(TAG, "检测到MEDIA_PLAY_PAUSE按键") |
|
|
|
handleDoubleClick() |
|
|
|
return true |
|
|
|
} |
|
|
|
else -> { |
|
|
|
Log.d(TAG, "检测到其他按键: ${keyEvent.keyCode}") |
|
|
|
} |
|
|
|
lastKeyEventTime = currentTime |
|
|
|
|
|
|
|
// 单击也处理 |
|
|
|
handleDoubleClick() |
|
|
|
return true |
|
|
|
} |
|
|
|
} else { |
|
|
|
Log.d(TAG, "非ACTION_DOWN事件: ${keyEvent.action}") |
|
|
|
} |
|
|
|
} else { |
|
|
|
Log.d(TAG, "Intent中没有KeyEvent") |
|
|
|
} |
|
|
|
return super.onMediaButtonEvent(mediaButtonEvent) |
|
|
|
} |
|
|
|
|
|
|
|
override fun onPlay() { |
|
|
|
Log.d(TAG, "收到onPlay回调") |
|
|
|
handleDoubleClick() |
|
|
|
return super.onPlay() |
|
|
|
} |
|
|
|
|
|
|
|
override fun onPause() { |
|
|
|
Log.d(TAG, "收到onPause回调") |
|
|
|
handleDoubleClick() |
|
|
|
return super.onPause() |
|
|
|
} |
|
|
|
@ -225,14 +269,20 @@ class VoiceInteractionService : Service() { |
|
|
|
|
|
|
|
// 激活 MediaSession |
|
|
|
mediaSession.isActive = true |
|
|
|
Log.d(TAG, "MediaSession已激活") |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 注册媒体按钮接收器 |
|
|
|
*/ |
|
|
|
private fun registerMediaButtonReceiver() { |
|
|
|
val mediaButtonReceiver = ComponentName(packageName, MediaButtonReceiver::class.java.name) |
|
|
|
audioManager.registerMediaButtonEventReceiver(mediaButtonReceiver) |
|
|
|
try { |
|
|
|
val mediaButtonReceiver = ComponentName(packageName, MediaButtonReceiver::class.java.name) |
|
|
|
audioManager.registerMediaButtonEventReceiver(mediaButtonReceiver) |
|
|
|
Log.d(TAG, "媒体按钮接收器注册成功: $mediaButtonReceiver") |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.e(TAG, "媒体按钮接收器注册失败: ${e.message}", e) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
@ -276,6 +326,8 @@ class VoiceInteractionService : Service() { |
|
|
|
* 处理双击事件 |
|
|
|
*/ |
|
|
|
private fun handleDoubleClick() { |
|
|
|
Log.d(TAG, "处理双击事件") |
|
|
|
|
|
|
|
// 停止当前TTS播放 |
|
|
|
stopCurrentTTS() |
|
|
|
|
|
|
|
@ -290,8 +342,10 @@ class VoiceInteractionService : Service() { |
|
|
|
|
|
|
|
// 启动或重置语音识别 |
|
|
|
if (!isRecognitionActive) { |
|
|
|
Log.d(TAG, "语音识别未激活,开始启动") |
|
|
|
startVoiceRecognition() |
|
|
|
} else { |
|
|
|
Log.d(TAG, "语音识别已激活,更新活动时间") |
|
|
|
updateLastActivityTime() |
|
|
|
hasSpeechDetected = false |
|
|
|
} |
|
|
|
@ -576,8 +630,12 @@ class VoiceInteractionService : Service() { |
|
|
|
* 当 Service 被启动时调用 |
|
|
|
*/ |
|
|
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { |
|
|
|
Log.d(TAG, "onStartCommand: intent=$intent, action=${intent?.action}") |
|
|
|
|
|
|
|
// 处理媒体按键 Intent |
|
|
|
if (intent?.action == Intent.ACTION_MEDIA_BUTTON) { |
|
|
|
Log.d(TAG, "收到媒体按钮Intent: ${intent.extras}") |
|
|
|
|
|
|
|
val keyEvent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { |
|
|
|
intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT, KeyEvent::class.java) |
|
|
|
} else { |
|
|
|
@ -586,17 +644,27 @@ class VoiceInteractionService : Service() { |
|
|
|
} |
|
|
|
|
|
|
|
if (keyEvent != null) { |
|
|
|
Log.d(TAG, "从Intent中解析到按键事件: action=${keyEvent.action}, keyCode=${keyEvent.keyCode}") |
|
|
|
handleKeyEvent(keyEvent) |
|
|
|
} else { |
|
|
|
Log.d(TAG, "Intent中没有按键事件,直接处理双击") |
|
|
|
handleDoubleClick() |
|
|
|
} |
|
|
|
} else if (intent?.action == ACTION_PAUSE_VOICE_INTERACTION) { |
|
|
|
// 处理来自 Flutter 的暂停请求 |
|
|
|
Log.d(TAG, "收到暂停请求") |
|
|
|
pauseVoiceInteraction() |
|
|
|
} else { |
|
|
|
Log.d(TAG, "收到其他Intent: action=${intent?.action}") |
|
|
|
} |
|
|
|
|
|
|
|
// 让 MediaSession 处理 Intent |
|
|
|
MediaButtonReceiver.handleIntent(mediaSession, intent) |
|
|
|
try { |
|
|
|
MediaButtonReceiver.handleIntent(mediaSession, intent) |
|
|
|
Log.d(TAG, "MediaButtonReceiver处理Intent完成") |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.e(TAG, "MediaButtonReceiver处理Intent失败: ${e.message}", e) |
|
|
|
} |
|
|
|
|
|
|
|
return START_STICKY |
|
|
|
} |
|
|
|
@ -605,28 +673,50 @@ class VoiceInteractionService : Service() { |
|
|
|
* 处理按键事件 |
|
|
|
*/ |
|
|
|
private fun handleKeyEvent(keyEvent: KeyEvent) { |
|
|
|
Log.d(TAG, "处理按键事件: action=${keyEvent.action}, keyCode=${keyEvent.keyCode}") |
|
|
|
|
|
|
|
if (keyEvent.action == KeyEvent.ACTION_DOWN) { |
|
|
|
when (keyEvent.keyCode) { |
|
|
|
KeyEvent.KEYCODE_MEDIA_PLAY, |
|
|
|
KeyEvent.KEYCODE_MEDIA_PAUSE, |
|
|
|
KeyEvent.KEYCODE_HEADSETHOOK, |
|
|
|
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> { |
|
|
|
KeyEvent.KEYCODE_MEDIA_PLAY -> { |
|
|
|
Log.d(TAG, "处理MEDIA_PLAY按键") |
|
|
|
handleDoubleClick() |
|
|
|
} |
|
|
|
KeyEvent.KEYCODE_MEDIA_PAUSE -> { |
|
|
|
Log.d(TAG, "处理MEDIA_PAUSE按键") |
|
|
|
handleDoubleClick() |
|
|
|
} |
|
|
|
KeyEvent.KEYCODE_HEADSETHOOK -> { |
|
|
|
Log.d(TAG, "处理HEADSETHOOK按键") |
|
|
|
// 检测双击 |
|
|
|
val currentTime = System.currentTimeMillis() |
|
|
|
val timeDiff = currentTime - lastKeyEventTime |
|
|
|
|
|
|
|
Log.d(TAG, "按键时间差: $timeDiff ms, 当前计数: $keyEventCount") |
|
|
|
|
|
|
|
if (timeDiff < 500) { // 500毫秒内的按键视为连续按键 |
|
|
|
keyEventCount++ |
|
|
|
Log.d(TAG, "连续按键,计数增加到: $keyEventCount") |
|
|
|
if (keyEventCount == 1) { // 这是第二次按键,即双击 |
|
|
|
Log.d(TAG, "检测到双击,执行处理") |
|
|
|
handleDoubleClick() |
|
|
|
keyEventCount = 0 |
|
|
|
} |
|
|
|
} else { |
|
|
|
Log.d(TAG, "非连续按键,重置计数") |
|
|
|
keyEventCount = 0 |
|
|
|
} |
|
|
|
lastKeyEventTime = currentTime |
|
|
|
} |
|
|
|
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> { |
|
|
|
Log.d(TAG, "处理MEDIA_PLAY_PAUSE按键") |
|
|
|
handleDoubleClick() |
|
|
|
} |
|
|
|
else -> { |
|
|
|
Log.d(TAG, "处理其他按键: ${keyEvent.keyCode}") |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
Log.d(TAG, "非ACTION_DOWN事件: ${keyEvent.action}") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -709,4 +799,38 @@ class VoiceInteractionService : Service() { |
|
|
|
// 发送广播 |
|
|
|
sendBroadcast(intent) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 测试媒体按钮事件处理 |
|
|
|
*/ |
|
|
|
private fun testMediaButtonEvent() { |
|
|
|
Log.d(TAG, "开始测试媒体按钮事件处理") |
|
|
|
|
|
|
|
try { |
|
|
|
// 创建一个模拟的HEADSETHOOK按键事件 |
|
|
|
val keyEvent = KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK) |
|
|
|
|
|
|
|
// 创建一个包含按键事件的Intent |
|
|
|
val intent = Intent(Intent.ACTION_MEDIA_BUTTON).apply { |
|
|
|
putExtra(Intent.EXTRA_KEY_EVENT, keyEvent) |
|
|
|
} |
|
|
|
|
|
|
|
// 直接调用onMediaButtonEvent方法 |
|
|
|
Log.d(TAG, "直接调用onMediaButtonEvent方法") |
|
|
|
val result = mediaSession.controller.dispatchMediaButtonEvent(keyEvent) |
|
|
|
Log.d(TAG, "dispatchMediaButtonEvent结果: $result") |
|
|
|
|
|
|
|
// 通过MediaButtonReceiver发送Intent |
|
|
|
Log.d(TAG, "通过MediaButtonReceiver发送Intent") |
|
|
|
MediaButtonReceiver.handleIntent(mediaSession, intent) |
|
|
|
|
|
|
|
// 直接调用handleKeyEvent方法 |
|
|
|
Log.d(TAG, "直接调用handleKeyEvent方法") |
|
|
|
handleKeyEvent(keyEvent) |
|
|
|
|
|
|
|
Log.d(TAG, "测试媒体按钮事件处理完成") |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.e(TAG, "测试媒体按钮事件处理失败: ${e.message}", e) |
|
|
|
} |
|
|
|
} |
|
|
|
} |