Commit 1f5969b893ad45a1c3cb5c2d5a473e596844f433
1 parent
1ea75f04
修复 练习和绘本播放音频问题
Showing
2 changed files
with
81 additions
and
49 deletions
lib/pages/practice/bloc/topic_picture_bloc.dart
@@ -24,16 +24,19 @@ part 'topic_picture_state.dart'; | @@ -24,16 +24,19 @@ part 'topic_picture_state.dart'; | ||
24 | enum VoicePlayState { | 24 | enum VoicePlayState { |
25 | ///未知 | 25 | ///未知 |
26 | unKnow, | 26 | unKnow, |
27 | + | ||
27 | ///播放中 | 28 | ///播放中 |
28 | playing, | 29 | playing, |
30 | + | ||
29 | ///播放完成 | 31 | ///播放完成 |
30 | completed, | 32 | completed, |
33 | + | ||
31 | ///播放终止 | 34 | ///播放终止 |
32 | stop | 35 | stop |
33 | } | 36 | } |
34 | 37 | ||
35 | -class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureState> { | ||
36 | - | 38 | +class TopicPictureBloc |
39 | + extends BaseSectionBloc<TopicPictureEvent, TopicPictureState> { | ||
37 | final PageController pageController; | 40 | final PageController pageController; |
38 | 41 | ||
39 | final String courseLessonId; | 42 | final String courseLessonId; |
@@ -68,7 +71,7 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -68,7 +71,7 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | ||
68 | 71 | ||
69 | bool get isVoicing => _isVoicing; | 72 | bool get isVoicing => _isVoicing; |
70 | 73 | ||
71 | - VoicePlayState get voicePlayState => _voicePlayState; | 74 | + VoicePlayState get voicePlayState => _voicePlayState; |
72 | 75 | ||
73 | late MethodChannel methodChannel; | 76 | late MethodChannel methodChannel; |
74 | 77 | ||
@@ -76,7 +79,8 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -76,7 +79,8 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | ||
76 | 79 | ||
77 | final BuildContext context; | 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 | on<CurrentPageIndexChangeEvent>(_pageControllerChange); | 84 | on<CurrentPageIndexChangeEvent>(_pageControllerChange); |
81 | on<VoicePlayStateChangeEvent>(_voicePlayStateChange); | 85 | on<VoicePlayStateChangeEvent>(_voicePlayStateChange); |
82 | on<XSVoiceResultEvent>(_voiceXsResult); | 86 | on<XSVoiceResultEvent>(_voiceXsResult); |
@@ -90,7 +94,8 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -90,7 +94,8 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | ||
90 | //音频播放器 | 94 | //音频播放器 |
91 | audioPlayer = AudioPlayer(); | 95 | audioPlayer = AudioPlayer(); |
92 | audioPlayer.onPlayerStateChanged.listen((event) async { | 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 | if (_isResultSoundPlaying) { | 99 | if (_isResultSoundPlaying) { |
95 | if (event != PlayerState.playing) { | 100 | if (event != PlayerState.playing) { |
96 | _isResultSoundPlaying = false; | 101 | _isResultSoundPlaying = false; |
@@ -131,28 +136,40 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -131,28 +136,40 @@ class TopicPictureBloc extends BaseSectionBloc<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 | methodChannel.setMethodCallHandler((call) async { | 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 | add(XSVoiceResultEvent(call.arguments)); | 146 | add(XSVoiceResultEvent(call.arguments)); |
138 | return; | 147 | return; |
139 | } | 148 | } |
140 | 149 | ||
141 | - if (call.method == 'voiceStart') {//评测开始 | 150 | + if (call.method == 'voiceStart') { |
151 | + //评测开始 | ||
142 | if (kDebugMode) { | 152 | if (kDebugMode) { |
143 | print('评测开始'); | 153 | print('评测开始'); |
144 | } | 154 | } |
145 | return; | 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 | if (kDebugMode) { | 162 | if (kDebugMode) { |
150 | print('评测结束'); | 163 | print('评测结束'); |
151 | } | 164 | } |
152 | return; | 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 | EasyLoading.showToast('评测失败'); | 173 | EasyLoading.showToast('评测失败'); |
157 | return; | 174 | return; |
158 | } | 175 | } |
@@ -161,7 +178,7 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -161,7 +178,7 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | ||
161 | } | 178 | } |
162 | 179 | ||
163 | @override | 180 | @override |
164 | - Future<void> close(){ | 181 | + Future<void> close() { |
165 | pageController.dispose(); | 182 | pageController.dispose(); |
166 | audioPlayer.release(); | 183 | audioPlayer.release(); |
167 | audioPlayer.dispose(); | 184 | audioPlayer.dispose(); |
@@ -172,7 +189,8 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -172,7 +189,8 @@ class TopicPictureBloc extends BaseSectionBloc<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 | try { | 194 | try { |
177 | await loading(() async { | 195 | await loading(() async { |
178 | _entity = await ListenDao.process(courseLessonId); | 196 | _entity = await ListenDao.process(courseLessonId); |
@@ -180,13 +198,14 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -180,13 +198,14 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | ||
180 | }); | 198 | }); |
181 | } catch (e) { | 199 | } catch (e) { |
182 | if (e is ApiException) { | 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 | await closePlayerResource(); | 209 | await closePlayerResource(); |
191 | debugPrint('翻页 $_currentPage->${event.pageIndex}'); | 210 | debugPrint('翻页 $_currentPage->${event.pageIndex}'); |
192 | if (_currentPage == _entity?.topics?.length) { | 211 | if (_currentPage == _entity?.topics?.length) { |
@@ -196,7 +215,7 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -196,7 +215,7 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | ||
196 | final topics = _entity?.topics?[_currentPage]; | 215 | final topics = _entity?.topics?[_currentPage]; |
197 | if (topics?.type != 3 && topics?.type != 4) { | 216 | if (topics?.type != 3 && topics?.type != 4) { |
198 | if (topics?.audioUrl != null) { | 217 | if (topics?.audioUrl != null) { |
199 | - final urlStr = topics?.audioUrl??''; | 218 | + final urlStr = topics?.audioUrl ?? ''; |
200 | if (urlStr.isNotEmpty) { | 219 | if (urlStr.isNotEmpty) { |
201 | debugPrint(urlStr); | 220 | debugPrint(urlStr); |
202 | await audioPlayer.play(UrlSource(urlStr)); | 221 | await audioPlayer.play(UrlSource(urlStr)); |
@@ -208,13 +227,15 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -208,13 +227,15 @@ class TopicPictureBloc extends BaseSectionBloc<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 | if (_forbiddenWhenCorrect) { | 232 | if (_forbiddenWhenCorrect) { |
213 | return; | 233 | return; |
214 | } | 234 | } |
215 | _selectItem = event.selectIndex; | 235 | _selectItem = event.selectIndex; |
216 | CourseProcessTopics? topics = _entity?.topics?[_currentPage]; | 236 | CourseProcessTopics? topics = _entity?.topics?[_currentPage]; |
217 | - CourseProcessTopicsTopicAnswerList? answerList = topics?.topicAnswerList?[_selectItem]; | 237 | + CourseProcessTopicsTopicAnswerList? answerList = |
238 | + topics?.topicAnswerList?[_selectItem]; | ||
218 | if (answerList?.correct == 0) { | 239 | if (answerList?.correct == 0) { |
219 | _playResultSound(false); | 240 | _playResultSound(false); |
220 | // showToast('继续加油哦',duration: const Duration(seconds: 2)); | 241 | // showToast('继续加油哦',duration: const Duration(seconds: 2)); |
@@ -226,35 +247,32 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -226,35 +247,32 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | ||
226 | } | 247 | } |
227 | 248 | ||
228 | ///初始化SDK | 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 | await audioPlayer.stop(); | 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 | if (result) { | 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 | _isVoicing = true; | 268 | _isVoicing = true; |
252 | emitter(XSVoiceTestState()); | 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 | methodChannel.invokeMethod('stopVoice'); | 276 | methodChannel.invokeMethod('stopVoice'); |
259 | } | 277 | } |
260 | 278 | ||
@@ -264,11 +282,12 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -264,11 +282,12 @@ class TopicPictureBloc extends BaseSectionBloc<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 | final Map args = event.message as Map; | 287 | final Map args = event.message as Map; |
269 | final result = args['result'] as Map; | 288 | final result = args['result'] as Map; |
270 | final overall = result['overall'].toString(); | 289 | final overall = result['overall'].toString(); |
271 | - showToast('测评成功,分数是$overall',duration: const Duration(seconds: 5)); | 290 | + showToast('测评成功,分数是$overall', duration: const Duration(seconds: 5)); |
272 | _isVoicing = false; | 291 | _isVoicing = false; |
273 | emitter(XSVoiceTestState()); | 292 | emitter(XSVoiceTestState()); |
274 | if (isLastPage()) { | 293 | if (isLastPage()) { |
@@ -277,20 +296,23 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -277,20 +296,23 @@ class TopicPictureBloc extends BaseSectionBloc<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 | emitter(VoicePlayStateChange()); | 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 | if (_forbiddenWhenCorrect) { | 307 | if (_forbiddenWhenCorrect) { |
287 | return; | 308 | return; |
288 | } | 309 | } |
289 | _forbiddenWhenCorrect = false; | 310 | _forbiddenWhenCorrect = false; |
290 | await closePlayerResource(); | 311 | await closePlayerResource(); |
291 | final topics = _entity?.topics?[_currentPage]; | 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 | Future<void> closePlayerResource() async { | 318 | Future<void> closePlayerResource() async { |
@@ -302,7 +324,8 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -302,7 +324,8 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | ||
302 | ///播放选择结果音效 | 324 | ///播放选择结果音效 |
303 | void _playResultSound(bool isCorrect) async { | 325 | void _playResultSound(bool isCorrect) async { |
304 | // await audioPlayer.stop(); | 326 | // await audioPlayer.stop(); |
305 | - if (audioPlayer.state == PlayerState.playing && _isResultSoundPlaying == false) { | 327 | + if (audioPlayer.state == PlayerState.playing && |
328 | + _isResultSoundPlaying == false) { | ||
306 | _voicePlayState = VoicePlayState.stop; | 329 | _voicePlayState = VoicePlayState.stop; |
307 | } | 330 | } |
308 | debugPrint("_playResultSound isCorrect=$isCorrect"); | 331 | debugPrint("_playResultSound isCorrect=$isCorrect"); |
@@ -324,13 +347,12 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | @@ -324,13 +347,12 @@ class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureSt | ||
324 | void showStepPage() { | 347 | void showStepPage() { |
325 | ///如果最后一页是语音问答题,评测完后自动翻页 | 348 | ///如果最后一页是语音问答题,评测完后自动翻页 |
326 | sectionComplete(() { | 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 | }, againSectionTap: () { | 356 | }, againSectionTap: () { |
335 | pageController.jumpToPage(0); | 357 | pageController.jumpToPage(0); |
336 | }); | 358 | }); |
lib/pages/reading/bloc/reading_bloc.dart
@@ -130,6 +130,9 @@ class ReadingPageBloc | @@ -130,6 +130,9 @@ class ReadingPageBloc | ||
130 | "setMethodCallHandler method=${call.method} arguments=${call.arguments}"); | 130 | "setMethodCallHandler method=${call.method} arguments=${call.arguments}"); |
131 | if (call.method == 'voiceResult') { | 131 | if (call.method == 'voiceResult') { |
132 | //评测结果 | 132 | //评测结果 |
133 | + await audioPlayer.setAudioContext(AudioContext()); | ||
134 | + await audioPlayer.setBalance(0.0); | ||
135 | + | ||
133 | add(XSVoiceResultEvent(call.arguments)); | 136 | add(XSVoiceResultEvent(call.arguments)); |
134 | return; | 137 | return; |
135 | } | 138 | } |
@@ -149,6 +152,9 @@ class ReadingPageBloc | @@ -149,6 +152,9 @@ class ReadingPageBloc | ||
149 | if (kDebugMode) { | 152 | if (kDebugMode) { |
150 | print(call.method == 'voiceEnd' ? '评测结束' : '评测取消'); | 153 | print(call.method == 'voiceEnd' ? '评测结束' : '评测取消'); |
151 | } | 154 | } |
155 | + await audioPlayer.setAudioContext(AudioContext()); | ||
156 | + await audioPlayer.setBalance(0.0); | ||
157 | + | ||
152 | _isRecording = false; | 158 | _isRecording = false; |
153 | add(OnXSVoiceStateChangeEvent()); | 159 | add(OnXSVoiceStateChangeEvent()); |
154 | return; | 160 | return; |
@@ -157,6 +163,9 @@ class ReadingPageBloc | @@ -157,6 +163,9 @@ class ReadingPageBloc | ||
157 | if (call.method == 'voiceFail') { | 163 | if (call.method == 'voiceFail') { |
158 | //评测失败 | 164 | //评测失败 |
159 | _isRecording = false; | 165 | _isRecording = false; |
166 | + await audioPlayer.setAudioContext(AudioContext()); | ||
167 | + await audioPlayer.setBalance(0.0); | ||
168 | + | ||
160 | EasyLoading.showToast('评测失败'); | 169 | EasyLoading.showToast('评测失败'); |
161 | return; | 170 | return; |
162 | } | 171 | } |
@@ -276,7 +285,8 @@ class ReadingPageBloc | @@ -276,7 +285,8 @@ class ReadingPageBloc | ||
276 | 285 | ||
277 | Future<void> _playAudio(String? audioUrl) async { | 286 | Future<void> _playAudio(String? audioUrl) async { |
278 | if (audioUrl!.isNotEmpty) { | 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 |