Commit 1f5969b893ad45a1c3cb5c2d5a473e596844f433

Authored by biao
1 parent 1ea75f04

修复 练习和绘本播放音频问题

lib/pages/practice/bloc/topic_picture_bloc.dart
... ... @@ -24,16 +24,19 @@ part 'topic_picture_state.dart';
24 24 enum VoicePlayState {
25 25 ///未知
26 26 unKnow,
  27 +
27 28 ///播放中
28 29 playing,
  30 +
29 31 ///播放完成
30 32 completed,
  33 +
31 34 ///播放终止
32 35 stop
33 36 }
34 37  
35   -class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureState> {
36   -
  38 +class TopicPictureBloc
  39 + extends BaseSectionBloc<TopicPictureEvent, TopicPictureState> {
37 40 final PageController pageController;
38 41  
39 42 final String courseLessonId;
... ... @@ -68,7 +71,7 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
68 71  
69 72 bool get isVoicing => _isVoicing;
70 73  
71   - VoicePlayState get voicePlayState => _voicePlayState;
  74 + VoicePlayState get voicePlayState => _voicePlayState;
72 75  
73 76 late MethodChannel methodChannel;
74 77  
... ... @@ -76,7 +79,8 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
76 79  
77 80 final BuildContext context;
78 81  
79   - TopicPictureBloc(this.context, this.pageController, this.courseLessonId) : super(TopicPictureInitial()) {
  82 + TopicPictureBloc(this.context, this.pageController, this.courseLessonId)
  83 + : super(TopicPictureInitial()) {
80 84 on<CurrentPageIndexChangeEvent>(_pageControllerChange);
81 85 on<VoicePlayStateChangeEvent>(_voicePlayStateChange);
82 86 on<XSVoiceResultEvent>(_voiceXsResult);
... ... @@ -90,7 +94,8 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
90 94 //音频播放器
91 95 audioPlayer = AudioPlayer();
92 96 audioPlayer.onPlayerStateChanged.listen((event) async {
93   - debugPrint('播放状态变化 _voicePlayState=$_voicePlayState event=$event _isResultSoundPlaying=$_isResultSoundPlaying _forbiddenWhenCorrect=$_forbiddenWhenCorrect');
  97 + debugPrint(
  98 + '播放状态变化 _voicePlayState=$_voicePlayState event=$event _isResultSoundPlaying=$_isResultSoundPlaying _forbiddenWhenCorrect=$_forbiddenWhenCorrect');
94 99 if (_isResultSoundPlaying) {
95 100 if (event != PlayerState.playing) {
96 101 _isResultSoundPlaying = false;
... ... @@ -131,28 +136,40 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
131 136 }
132 137 });
133 138  
134   - methodChannel = const MethodChannel('wow_english/sing_sound_method_channel');
  139 + methodChannel =
  140 + const MethodChannel('wow_english/sing_sound_method_channel');
135 141 methodChannel.setMethodCallHandler((call) async {
136   - if (call.method == 'voiceResult') {//评测结果
  142 + if (call.method == 'voiceResult') {
  143 + //评测结果
  144 + await audioPlayer.setAudioContext(AudioContext());
  145 + await audioPlayer.setBalance(0.0);
137 146 add(XSVoiceResultEvent(call.arguments));
138 147 return;
139 148 }
140 149  
141   - if (call.method == 'voiceStart') {//评测开始
  150 + if (call.method == 'voiceStart') {
  151 + //评测开始
142 152 if (kDebugMode) {
143 153 print('评测开始');
144 154 }
145 155 return;
146 156 }
147 157  
148   - if (call.method == 'voiceEnd') {//评测结束
  158 + if (call.method == 'voiceEnd') {
  159 + await audioPlayer.setAudioContext(AudioContext());
  160 + await audioPlayer.setBalance(0.0);
  161 + //评测结束
149 162 if (kDebugMode) {
150 163 print('评测结束');
151 164 }
152 165 return;
153 166 }
154 167  
155   - if (call.method == 'voiceFail') {//评测失败
  168 + if (call.method == 'voiceFail') {
  169 + //评测失败
  170 + await audioPlayer.setAudioContext(AudioContext());
  171 + await audioPlayer.setBalance(0.0);
  172 +
156 173 EasyLoading.showToast('评测失败');
157 174 return;
158 175 }
... ... @@ -161,7 +178,7 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
161 178 }
162 179  
163 180 @override
164   - Future<void> close(){
  181 + Future<void> close() {
165 182 pageController.dispose();
166 183 audioPlayer.release();
167 184 audioPlayer.dispose();
... ... @@ -172,7 +189,8 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
172 189 }
173 190  
174 191 ///请求数据
175   - void _requestData(RequestDataEvent event,Emitter<TopicPictureState> emitter) async {
  192 + void _requestData(
  193 + RequestDataEvent event, Emitter<TopicPictureState> emitter) async {
176 194 try {
177 195 await loading(() async {
178 196 _entity = await ListenDao.process(courseLessonId);
... ... @@ -180,13 +198,14 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
180 198 });
181 199 } catch (e) {
182 200 if (e is ApiException) {
183   - showToast(e.message??'请求失败,请检查网络连接');
  201 + showToast(e.message ?? '请求失败,请检查网络连接');
184 202 }
185 203 }
186 204 }
187 205  
188 206 ///页面切换
189   - void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter<TopicPictureState> emitter) async {
  207 + void _pageControllerChange(CurrentPageIndexChangeEvent event,
  208 + Emitter<TopicPictureState> emitter) async {
190 209 await closePlayerResource();
191 210 debugPrint('翻页 $_currentPage->${event.pageIndex}');
192 211 if (_currentPage == _entity?.topics?.length) {
... ... @@ -196,7 +215,7 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
196 215 final topics = _entity?.topics?[_currentPage];
197 216 if (topics?.type != 3 && topics?.type != 4) {
198 217 if (topics?.audioUrl != null) {
199   - final urlStr = topics?.audioUrl??'';
  218 + final urlStr = topics?.audioUrl ?? '';
200 219 if (urlStr.isNotEmpty) {
201 220 debugPrint(urlStr);
202 221 await audioPlayer.play(UrlSource(urlStr));
... ... @@ -208,13 +227,15 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
208 227 }
209 228  
210 229 ///选择
211   - void _selectItemLoad(SelectItemEvent event,Emitter<TopicPictureState> emitter) async {
  230 + void _selectItemLoad(
  231 + SelectItemEvent event, Emitter<TopicPictureState> emitter) async {
212 232 if (_forbiddenWhenCorrect) {
213 233 return;
214 234 }
215 235 _selectItem = event.selectIndex;
216 236 CourseProcessTopics? topics = _entity?.topics?[_currentPage];
217   - CourseProcessTopicsTopicAnswerList? answerList = topics?.topicAnswerList?[_selectItem];
  237 + CourseProcessTopicsTopicAnswerList? answerList =
  238 + topics?.topicAnswerList?[_selectItem];
218 239 if (answerList?.correct == 0) {
219 240 _playResultSound(false);
220 241 // showToast('继续加油哦',duration: const Duration(seconds: 2));
... ... @@ -226,35 +247,32 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
226 247 }
227 248  
228 249 ///初始化SDK
229   - _initVoiceSdk(XSVoiceInitEvent event,Emitter<TopicPictureState> emitter) async {
230   - methodChannel.invokeMethod('initVoiceSdk',event.data);
  250 + _initVoiceSdk(
  251 + XSVoiceInitEvent event, Emitter<TopicPictureState> emitter) async {
  252 + methodChannel.invokeMethod('initVoiceSdk', event.data);
231 253 }
232 254  
233 255 ///先声测试
234   - void _voiceXsStart(XSVoiceStartEvent event,Emitter<TopicPictureState> emitter) async {
  256 + void _voiceXsStart(
  257 + XSVoiceStartEvent event, Emitter<TopicPictureState> emitter) async {
235 258 await audioPlayer.stop();
236 259 // 调用封装好的权限检查和请求方法
237   - bool result = await permissionCheckAndRequest(
238   - context,
239   - Permission.microphone,
240   - "录音"
241   - );
  260 + bool result =
  261 + await permissionCheckAndRequest(context, Permission.microphone, "录音");
242 262 if (result) {
243   - methodChannel.invokeMethod(
244   - 'startVoice',
245   - {
246   - 'word': event.testWord,
247   - 'type': event.type,
248   - 'userId': event.userId.toString()
249   - }
250   - );
  263 + methodChannel.invokeMethod('startVoice', {
  264 + 'word': event.testWord,
  265 + 'type': event.type,
  266 + 'userId': event.userId.toString()
  267 + });
251 268 _isVoicing = true;
252 269 emitter(XSVoiceTestState());
253 270 }
254 271 }
255 272  
256 273 ///终止评测
257   - void _voiceXsStop(XSVoiceStopEvent event,Emitter<TopicPictureState> emitter) async {
  274 + void _voiceXsStop(
  275 + XSVoiceStopEvent event, Emitter<TopicPictureState> emitter) async {
258 276 methodChannel.invokeMethod('stopVoice');
259 277 }
260 278  
... ... @@ -264,11 +282,12 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
264 282 }
265 283  
266 284 ///先声评测结果
267   - void _voiceXsResult(XSVoiceResultEvent event,Emitter<TopicPictureState> emitter) async {
  285 + void _voiceXsResult(
  286 + XSVoiceResultEvent event, Emitter<TopicPictureState> emitter) async {
268 287 final Map args = event.message as Map;
269 288 final result = args['result'] as Map;
270 289 final overall = result['overall'].toString();
271   - showToast('测评成功,分数是$overall',duration: const Duration(seconds: 5));
  290 + showToast('测评成功,分数是$overall', duration: const Duration(seconds: 5));
272 291 _isVoicing = false;
273 292 emitter(XSVoiceTestState());
274 293 if (isLastPage()) {
... ... @@ -277,20 +296,23 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
277 296 }
278 297  
279 298 // 暂时没用上
280   - void _voicePlayStateChange(VoicePlayStateChangeEvent event,Emitter<TopicPictureState> emitter) async {
  299 + void _voicePlayStateChange(VoicePlayStateChangeEvent event,
  300 + Emitter<TopicPictureState> emitter) async {
281 301 emitter(VoicePlayStateChange());
282 302 }
283 303  
284 304 // 题目音频播放
285   - void _questionVoicePlay(VoicePlayEvent event,Emitter<TopicPictureState> emitter) async {
  305 + void _questionVoicePlay(
  306 + VoicePlayEvent event, Emitter<TopicPictureState> emitter) async {
286 307 if (_forbiddenWhenCorrect) {
287 308 return;
288 309 }
289 310 _forbiddenWhenCorrect = false;
290 311 await closePlayerResource();
291 312 final topics = _entity?.topics?[_currentPage];
292   - final urlStr = topics?.audioUrl??'';
293   - await audioPlayer.play(UrlSource(urlStr));
  313 + final urlStr = topics?.audioUrl ?? '';
  314 + await audioPlayer.play(UrlSource(urlStr),
  315 + balance: 0.0, ctx: AudioContext());
294 316 }
295 317  
296 318 Future<void> closePlayerResource() async {
... ... @@ -302,7 +324,8 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
302 324 ///播放选择结果音效
303 325 void _playResultSound(bool isCorrect) async {
304 326 // await audioPlayer.stop();
305   - if (audioPlayer.state == PlayerState.playing && _isResultSoundPlaying == false) {
  327 + if (audioPlayer.state == PlayerState.playing &&
  328 + _isResultSoundPlaying == false) {
306 329 _voicePlayState = VoicePlayState.stop;
307 330 }
308 331 debugPrint("_playResultSound isCorrect=$isCorrect");
... ... @@ -324,13 +347,12 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
324 347 void showStepPage() {
325 348 ///如果最后一页是语音问答题,评测完后自动翻页
326 349 sectionComplete(() {
327   - popPage(
328   - data:{
329   - 'currentStep':currentPage,
330   - 'courseLessonId':courseLessonId,
331   - 'isCompleted': true,
332   - 'nextSection': true
333   - });
  350 + popPage(data: {
  351 + 'currentStep': currentPage,
  352 + 'courseLessonId': courseLessonId,
  353 + 'isCompleted': true,
  354 + 'nextSection': true
  355 + });
334 356 }, againSectionTap: () {
335 357 pageController.jumpToPage(0);
336 358 });
... ...
lib/pages/reading/bloc/reading_bloc.dart
... ... @@ -130,6 +130,9 @@ class ReadingPageBloc
130 130 "setMethodCallHandler method=${call.method} arguments=${call.arguments}");
131 131 if (call.method == 'voiceResult') {
132 132 //评测结果
  133 + await audioPlayer.setAudioContext(AudioContext());
  134 + await audioPlayer.setBalance(0.0);
  135 +
133 136 add(XSVoiceResultEvent(call.arguments));
134 137 return;
135 138 }
... ... @@ -149,6 +152,9 @@ class ReadingPageBloc
149 152 if (kDebugMode) {
150 153 print(call.method == 'voiceEnd' ? '评测结束' : '评测取消');
151 154 }
  155 + await audioPlayer.setAudioContext(AudioContext());
  156 + await audioPlayer.setBalance(0.0);
  157 +
152 158 _isRecording = false;
153 159 add(OnXSVoiceStateChangeEvent());
154 160 return;
... ... @@ -157,6 +163,9 @@ class ReadingPageBloc
157 163 if (call.method == 'voiceFail') {
158 164 //评测失败
159 165 _isRecording = false;
  166 + await audioPlayer.setAudioContext(AudioContext());
  167 + await audioPlayer.setBalance(0.0);
  168 +
160 169 EasyLoading.showToast('评测失败');
161 170 return;
162 171 }
... ... @@ -276,7 +285,8 @@ class ReadingPageBloc
276 285  
277 286 Future<void> _playAudio(String? audioUrl) async {
278 287 if (audioUrl!.isNotEmpty) {
279   - await audioPlayer.play(UrlSource(audioUrl));
  288 + await audioPlayer.play(UrlSource(audioUrl),
  289 + balance: 0.0, ctx: AudioContext());
280 290 }
281 291 }
282 292  
... ...