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,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&lt;TopicPictureEvent, TopicPictureSt @@ -68,7 +71,7 @@ class TopicPictureBloc extends BaseSectionBloc&lt;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&lt;TopicPictureEvent, TopicPictureSt @@ -76,7 +79,8 @@ class TopicPictureBloc extends BaseSectionBloc&lt;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&lt;TopicPictureEvent, TopicPictureSt @@ -90,7 +94,8 @@ class TopicPictureBloc extends BaseSectionBloc&lt;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&lt;TopicPictureEvent, TopicPictureSt @@ -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 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&lt;TopicPictureEvent, TopicPictureSt @@ -161,7 +178,7 @@ class TopicPictureBloc extends BaseSectionBloc&lt;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&lt;TopicPictureEvent, TopicPictureSt @@ -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 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&lt;TopicPictureEvent, TopicPictureSt @@ -180,13 +198,14 @@ class TopicPictureBloc extends BaseSectionBloc&lt;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&lt;TopicPictureEvent, TopicPictureSt @@ -196,7 +215,7 @@ class TopicPictureBloc extends BaseSectionBloc&lt;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&lt;TopicPictureEvent, TopicPictureSt @@ -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 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&lt;TopicPictureEvent, TopicPictureSt @@ -226,35 +247,32 @@ class TopicPictureBloc extends BaseSectionBloc&lt;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&lt;TopicPictureEvent, TopicPictureSt @@ -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 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&lt;TopicPictureEvent, TopicPictureSt @@ -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 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&lt;TopicPictureEvent, TopicPictureSt @@ -302,7 +324,8 @@ class TopicPictureBloc extends BaseSectionBloc&lt;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&lt;TopicPictureEvent, TopicPictureSt @@ -324,13 +347,12 @@ class TopicPictureBloc extends BaseSectionBloc&lt;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