提交 8631150a authored 作者: songchuancai's avatar songchuancai

优化语音功能

上级 104d31dd
......@@ -8,7 +8,7 @@ if (localPropertiesFile.exists()) {
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
throw new FileNotFoundException ("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
......
......@@ -5,6 +5,8 @@
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<queries>
<intent>
<action android:name="android.speech.RecognitionService" />
......
......@@ -92,6 +92,8 @@ class _HomePageState extends State<HomePage> {
int _currentIndex = 0;
bool _hasSpeechPermission = false;
@override
void initState() {
super.initState();
......@@ -162,15 +164,47 @@ class _HomePageState extends State<HomePage> {
}
Future<void> initSpeechToText() async {
await speechToText.initialize();
try {
_hasSpeechPermission = await speechToText.initialize(
onStatus: (status) {
print('语音状态: $status');
if (status == 'notListening') {
setState(() => _isListeningPressed = false);
}
},
onError: (error) {
print('语音错误: $error');
setState(() => _isListeningPressed = false);
_showErrorDialog('语音初始化失败,请检查麦克风权限');
},
);
} catch (e) {
print('语音初始化错误: $e');
_hasSpeechPermission = false;
}
setState(() {});
}
Future<void> startListening() async {
await speechToText.listen(onResult: onSpeechResult);
if (!_hasSpeechPermission) {
_showErrorDialog('请先授予麦克风权限');
setState(() => _isListeningPressed = false);
return;
}
setState(() {});
try {
await speechToText.listen(
onResult: onSpeechResult,
localeId: 'zh_CN',
listenMode: ListenMode.confirmation,
cancelOnError: true,
partialResults: true,
);
} catch (e) {
print('开始录音失败: $e');
setState(() => _isListeningPressed = false);
_showErrorDialog('启动语音识别失败,请重试');
}
}
Future<void> stopListening() async {
......@@ -372,38 +406,32 @@ class _HomePageState extends State<HomePage> {
Expanded(
child: _isVoiceMode
? GestureDetector(
onLongPressStart: (_) async {
onTap: () async {
if (!_isListeningPressed) {
// 开始录音
setState(() {
_isListeningPressed = true;
_currentVoiceText = '';
});
await startListening();
},
onLongPressEnd: (_) async {
} else {
// 停止录音
setState(() => _isListeningPressed = false);
await stopListening();
final finalVoiceText = _currentVoiceText;
if (finalVoiceText.isNotEmpty) {
// 确保有语音文本才处理
if (_currentVoiceText.isNotEmpty) {
setState(() {
messages.add(ChatMessage(
text: finalVoiceText,
text: _currentVoiceText,
isUserMessage: true,
));
_isLoading = true;
});
await _processAIResponse(finalVoiceText);
await _processAIResponse(_currentVoiceText);
}
setState(() => _currentVoiceText = '');
}
setState(() {
_currentVoiceText = '';
});
},
child: Container(
padding: const EdgeInsets.symmetric(
......@@ -414,12 +442,20 @@ class _HomePageState extends State<HomePage> {
color: Colors.grey[100],
borderRadius: BorderRadius.circular(25),
),
child: Text(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
_isListeningPressed ? Icons.stop : Icons.mic,
color: _isListeningPressed
? Pallete.firstSuggestionBoxColor
: Colors.grey[600],
),
const SizedBox(width: 8),
Text(
_isListeningPressed
? (_currentVoiceText.isEmpty
? '正在聆听...'
: _currentVoiceText)
: '按住说话',
? (_currentVoiceText.isEmpty ? '点击停止' : _currentVoiceText)
: '点击说话',
textAlign: TextAlign.center,
style: TextStyle(
color: _isListeningPressed
......@@ -427,6 +463,8 @@ class _HomePageState extends State<HomePage> {
: Colors.grey[600],
),
),
],
),
),
)
: TextField(
......@@ -703,7 +741,7 @@ class _HomePageState extends State<HomePage> {
),
const SizedBox(width: 8),
Text(
'退出登录',
'出登录',
style: TextStyle(
color: Colors.red[700],
fontSize: 16,
......@@ -724,6 +762,22 @@ class _HomePageState extends State<HomePage> {
);
}
void _showErrorDialog(String message) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('提示'),
content: Text(message),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('确定'),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
......@@ -850,3 +904,4 @@ class _HomePageState extends State<HomePage> {
);
}
}
\ No newline at end of file
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论