You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

273 lines
7.3 KiB

import 'dart:async';
import 'package:audio_service/audio_service.dart';
import 'package:get/get.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'background_agent_service.dart';
import '../../data/providers/agent_provider.dart';
/// 自定义 AudioHandler,用于捕获媒体按键事件(例如蓝牙耳机按钮)
class MyAudioHandler extends BaseAudioHandler {
// 定义一个 StreamController 用于向 UI 发送自定义事件
final StreamController<dynamic> _customEventController =
StreamController.broadcast();
bool _isDisposed = false;
BackgroundAgentService? _backgroundAgent;
String _systemPrompt = '';
// 添加一个标志,表示是否正在处理交互
bool _isHandlingInteraction = false;
Stream<dynamic> get customEventStream => _customEventController.stream;
MyAudioHandler() {
_initializeHandler();
_initializeBackgroundAgent();
_initializeSystemPrompt();
print('MyAudioHandler 已创建,准备接收媒体按钮事件');
}
void _initializeSystemPrompt() {
try {
final agent = AgentProvider.getAgentById('personal_assistant');
_systemPrompt = agent?.systemPrompt ?? '';
} catch (e) {
print('初始化 SystemPrompt 失败: $e');
_systemPrompt = '';
}
}
void _initializeBackgroundAgent() {
try {
if (Get.isRegistered<BackgroundAgentService>()) {
_backgroundAgent = Get.find<BackgroundAgentService>();
} else {
_backgroundAgent = Get.put(BackgroundAgentService(), permanent: true);
}
print('BackgroundAgent 初始化成功');
} catch (e) {
print('初始化 BackgroundAgent 失败: $e');
_backgroundAgent = null;
}
}
void _initializeHandler() {
try {
// 设置初始播放状态
playbackState.add(PlaybackState(
controls: [
MediaControl.play,
MediaControl.pause,
MediaControl.stop,
MediaControl.skipToPrevious,
MediaControl.skipToNext,
],
systemActions: {
MediaAction.play,
MediaAction.pause,
MediaAction.stop,
MediaAction.skipToPrevious,
MediaAction.skipToNext,
MediaAction.seek,
},
androidCompactActionIndices: const [0, 1, 2],
processingState: AudioProcessingState.idle,
playing: false,
));
// 设置媒体元数据
final item = MediaItem(
id: 'deep_voice_audio',
title: 'Deep Voice Audio',
album: 'Deep Voice',
artist: 'Deep Voice',
genre: 'Speech',
duration: const Duration(seconds: 1),
artUri: null, // 移除图片URI
playable: true,
displayTitle: 'Deep Voice Audio',
displaySubtitle: 'Voice Assistant',
displayDescription: 'TTS Audio',
extras: const {'source': 'deep_voice'},
);
mediaItem.add(item);
print('AudioHandler 媒体项已设置');
} catch (e) {
print('初始化 AudioHandler 失败: $e');
}
}
// 更新播放状态
void _updatePlaybackState({
required bool playing,
required AudioProcessingState processingState,
}) {
if (_isDisposed) return;
try {
playbackState.add(playbackState.value.copyWith(
playing: playing,
processingState: processingState,
updatePosition: Duration.zero,
));
} catch (e) {
print('更新播放状态失败: $e');
}
}
Future<void> _handleInteraction() async {
print('处理媒体按钮交互');
// 防止重复处理
if (_isHandlingInteraction) {
print('已经在处理交互,忽略此次请求');
return;
}
_isHandlingInteraction = true;
try {
if (_systemPrompt.isEmpty) {
print('系统提示为空,无法激活语音助手');
return;
}
if (Get.context != null &&
WidgetsBinding.instance.lifecycleState == AppLifecycleState.resumed) {
// 应用在前台,导航到聊天页面
print('应用在前台,导航到聊天页面');
final agent = AgentProvider.getAgentById('personal_assistant');
if (agent != null) {
// 导航到聊天页面,并标记需要在进入时播放语音应答
Get.toNamed('/chat', arguments: {
'agentId': agent.id,
'agentName': agent.name,
'agentAvatar': agent.avatarUrl,
'agentSubtitle': agent.description,
'systemPrompt': agent.systemPrompt,
'welcomeMessage': agent.welcomeMessage,
'playVoiceOnEnter': true,
});
}
} else {
// 应用在后台,使用 BackgroundAgent 处理交互
print('应用在后台,使用 BackgroundAgent 处理交互');
if (_backgroundAgent != null) {
// 调用 BackgroundAgent 的语音识别和 AI 交互功能
await _backgroundAgent!.handleAgentInteraction(_systemPrompt);
} else {
print('BackgroundAgent 未初始化,无法处理交互');
}
}
} catch (e) {
print('处理媒体按钮交互失败: $e');
} finally {
_isHandlingInteraction = false;
}
}
@override
Future<void> play() async {
print('收到播放命令');
try {
await _handleInteraction();
_updatePlaybackState(
playing: true,
processingState: AudioProcessingState.ready,
);
} catch (e) {
print('处理播放命令失败: $e');
}
}
@override
Future<void> pause() async {
print('收到暂停命令');
try {
await _handleInteraction();
_updatePlaybackState(
playing: false,
processingState: AudioProcessingState.ready,
);
} catch (e) {
print('处理暂停命令失败: $e');
}
}
@override
Future<void> stop() async {
print('停止 AudioHandler');
_isDisposed = true;
try {
await super.stop();
_customEventController.close();
_updatePlaybackState(
playing: false,
processingState: AudioProcessingState.idle,
);
} catch (e) {
print('停止 AudioHandler 时发生错误: $e');
}
}
@override
Future<void> skipToPrevious() async {
print('收到上一曲命令');
try {
await _handleInteraction();
} catch (e) {
print('处理上一曲命令失败: $e');
}
}
@override
Future<void> skipToNext() async {
print('收到下一曲命令');
try {
await _handleInteraction();
} catch (e) {
print('处理下一曲命令失败: $e');
}
}
@override
Future<void> seek(Duration position) async {
print('收到跳转命令: $position');
}
@override
Future<dynamic> customAction(String name,
[Map<String, dynamic>? extras]) async {
print('收到自定义命令: $name');
try {
if (name == 'media_button') {
print('收到媒体按钮事件');
await _handleInteraction();
}
} catch (e) {
print('处理自定义命令失败: $e');
}
return null;
}
@override
Future<void> onTaskRemoved() async {
print('服务被系统移除');
try {
await stop();
} catch (e) {
print('处理服务移除失败: $e');
}
}
@override
Future<void> onNotificationDeleted() async {
print('通知被用户移除');
try {
await stop();
} catch (e) {
print('处理通知移除失败: $e');
}
}
}