9 changed files with 359 additions and 104 deletions
Unified View
Diff Options
-
67ios/Podfile.lock
-
8ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
-
8ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
-
96lib/controller/message/voice_player_manager.dart
-
104lib/pages/message/chat_page.dart
-
1lib/widget/message/message_item.dart
-
122lib/widget/message/voice_item.dart
-
56pubspec.lock
-
1pubspec.yaml
@ -1,8 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|
||||
<plist version="1.0"> |
|
||||
<dict> |
|
||||
<key>IDEDidComputeMac32BitWarning</key> |
|
||||
<true/> |
|
||||
</dict> |
|
||||
</plist> |
|
||||
@ -1,8 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|
||||
<plist version="1.0"> |
|
||||
<dict> |
|
||||
<key>PreviewsEnabled</key> |
|
||||
<false/> |
|
||||
</dict> |
|
||||
</plist> |
|
||||
@ -0,0 +1,96 @@ |
|||||
|
import 'package:audioplayers/audioplayers.dart'; |
||||
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
|
import 'package:get/get.dart'; |
||||
|
|
||||
|
/// 语音播放管理器,单例模式,统一管理语音播放 |
||||
|
class VoicePlayerManager extends GetxController { |
||||
|
static VoicePlayerManager? _instance; |
||||
|
static VoicePlayerManager get instance { |
||||
|
_instance ??= Get.put(VoicePlayerManager()); |
||||
|
return _instance!; |
||||
|
} |
||||
|
|
||||
|
final AudioPlayer _audioPlayer = AudioPlayer(); |
||||
|
String? _currentPlayingId; |
||||
|
final Rx<String?> currentPlayingId = Rx<String?>(null); |
||||
|
final Rx<PlayerState> playerState = Rx<PlayerState>(PlayerState.stopped); |
||||
|
|
||||
|
VoicePlayerManager() { |
||||
|
// 监听播放状态变化 |
||||
|
_audioPlayer.onPlayerStateChanged.listen((state) { |
||||
|
playerState.value = state; |
||||
|
if (state == PlayerState.completed) { |
||||
|
// 播放完成,重置状态 |
||||
|
_currentPlayingId = null; |
||||
|
currentPlayingId.value = null; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/// 播放音频 |
||||
|
/// [audioId] 音频的唯一标识(通常是消息ID) |
||||
|
/// [filePath] 音频文件路径 |
||||
|
Future<void> play(String audioId, String filePath) async { |
||||
|
try { |
||||
|
// 如果正在播放其他音频,先停止 |
||||
|
if (_currentPlayingId != null && _currentPlayingId != audioId) { |
||||
|
await stop(); |
||||
|
} |
||||
|
|
||||
|
// 如果是同一个音频,则暂停/恢复 |
||||
|
if (_currentPlayingId == audioId) { |
||||
|
if (playerState.value == PlayerState.playing) { |
||||
|
await _audioPlayer.pause(); |
||||
|
} else { |
||||
|
await _audioPlayer.resume(); |
||||
|
} |
||||
|
return; |
||||
|
} |
||||
|
// 播放新音频 |
||||
|
_currentPlayingId = audioId; |
||||
|
currentPlayingId.value = audioId; |
||||
|
await _audioPlayer.play(DeviceFileSource(filePath)); |
||||
|
} catch (e) { |
||||
|
print('播放音频失败: $e'); |
||||
|
_currentPlayingId = null; |
||||
|
currentPlayingId.value = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// 停止播放 |
||||
|
Future<void> stop() async { |
||||
|
try { |
||||
|
await _audioPlayer.stop(); |
||||
|
_currentPlayingId = null; |
||||
|
currentPlayingId.value = null; |
||||
|
} catch (e) { |
||||
|
print('停止播放失败: $e'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// 暂停播放 |
||||
|
Future<void> pause() async { |
||||
|
try { |
||||
|
await _audioPlayer.pause(); |
||||
|
} catch (e) { |
||||
|
print('暂停播放失败: $e'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// 检查指定音频是否正在播放 |
||||
|
bool isPlaying(String audioId) { |
||||
|
return _currentPlayingId == audioId && |
||||
|
playerState.value == PlayerState.playing; |
||||
|
} |
||||
|
|
||||
|
/// 检查指定音频是否已加载 |
||||
|
bool isLoaded(String audioId) { |
||||
|
return _currentPlayingId == audioId; |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
void onClose() { |
||||
|
_audioPlayer.dispose(); |
||||
|
super.onClose(); |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save