Commit b1869cf8c5a103abd2206171c56033fe68ce78c8
1 parent
d5fb5080
背景音乐添加
Showing
11 changed files
with
187 additions
and
77 deletions
lib/pages/games/bloc.dart
| @@ -2,17 +2,17 @@ import 'package:bloc/bloc.dart'; | @@ -2,17 +2,17 @@ import 'package:bloc/bloc.dart'; | ||
| 2 | import 'package:flutter/cupertino.dart'; | 2 | import 'package:flutter/cupertino.dart'; |
| 3 | import 'package:flutter/services.dart'; | 3 | import 'package:flutter/services.dart'; |
| 4 | import 'package:wow_english/common/extension/string_extension.dart'; | 4 | import 'package:wow_english/common/extension/string_extension.dart'; |
| 5 | +import 'package:wow_english/utils/audioplayer_util.dart'; | ||
| 5 | 6 | ||
| 6 | import 'event.dart'; | 7 | import 'event.dart'; |
| 7 | import 'game_entity.dart'; | 8 | import 'game_entity.dart'; |
| 8 | import 'state.dart'; | 9 | import 'state.dart'; |
| 9 | 10 | ||
| 10 | class GamesBloc extends Bloc<GamesEvent, GamesState> { | 11 | class GamesBloc extends Bloc<GamesEvent, GamesState> { |
| 11 | - | ||
| 12 | late MethodChannel _methodChannel; | 12 | late MethodChannel _methodChannel; |
| 13 | 13 | ||
| 14 | //手动初始化4个GameEntity对象 | 14 | //手动初始化4个GameEntity对象 |
| 15 | - final List<GameEntity> _games = [ | 15 | + final List<GameEntity> _games = [ |
| 16 | GameEntity() | 16 | GameEntity() |
| 17 | ..id = 1 | 17 | ..id = 1 |
| 18 | ..imageName = 'game_food_1'.assetPng | 18 | ..imageName = 'game_food_1'.assetPng |
| @@ -31,7 +31,7 @@ class GamesBloc extends Bloc<GamesEvent, GamesState> { | @@ -31,7 +31,7 @@ class GamesBloc extends Bloc<GamesEvent, GamesState> { | ||
| 31 | ..name = 'Animal' | 31 | ..name = 'Animal' |
| 32 | ]; | 32 | ]; |
| 33 | 33 | ||
| 34 | - List<GameEntity> get listData => _games; | 34 | + List<GameEntity> get listData => _games; |
| 35 | 35 | ||
| 36 | GamesBloc() : super(GamesState().init()) { | 36 | GamesBloc() : super(GamesState().init()) { |
| 37 | on<InitEvent>(_init); | 37 | on<InitEvent>(_init); |
| @@ -39,13 +39,16 @@ class GamesBloc extends Bloc<GamesEvent, GamesState> { | @@ -39,13 +39,16 @@ class GamesBloc extends Bloc<GamesEvent, GamesState> { | ||
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | void _init(InitEvent event, Emitter<GamesState> emit) async { | 41 | void _init(InitEvent event, Emitter<GamesState> emit) async { |
| 42 | + AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.inMyTummy); | ||
| 42 | emit(state.clone()); | 43 | emit(state.clone()); |
| 43 | } | 44 | } |
| 44 | 45 | ||
| 45 | void _gotoGamePage(GotoGamePageEvent event, Emitter<GamesState> emit) async { | 46 | void _gotoGamePage(GotoGamePageEvent event, Emitter<GamesState> emit) async { |
| 47 | + AudioPlayerUtil.getInstance().pause(); | ||
| 46 | try { | 48 | try { |
| 47 | _methodChannel = const MethodChannel('wow_english/game_method_channel'); | 49 | _methodChannel = const MethodChannel('wow_english/game_method_channel'); |
| 48 | - await _methodChannel.invokeMethod('openGamePage', { "gameId": event.gameId }); | 50 | + await _methodChannel |
| 51 | + .invokeMethod('openGamePage', {"gameId": event.gameId}); | ||
| 49 | } on PlatformException catch (e) { | 52 | } on PlatformException catch (e) { |
| 50 | debugPrint("Failed to go to native page: '${e.message}'."); | 53 | debugPrint("Failed to go to native page: '${e.message}'."); |
| 51 | } | 54 | } |
lib/pages/home/bloc.dart
| @@ -2,6 +2,7 @@ import 'package:audioplayers/audioplayers.dart'; | @@ -2,6 +2,7 @@ import 'package:audioplayers/audioplayers.dart'; | ||
| 2 | import 'package:bloc/bloc.dart'; | 2 | import 'package:bloc/bloc.dart'; |
| 3 | import 'package:wow_english/common/core/user_util.dart'; | 3 | import 'package:wow_english/common/core/user_util.dart'; |
| 4 | import 'package:wow_english/common/extension/string_extension.dart'; | 4 | import 'package:wow_english/common/extension/string_extension.dart'; |
| 5 | +import 'package:wow_english/utils/audioplayer_util.dart'; | ||
| 5 | 6 | ||
| 6 | import '../../common/core/app_config_helper.dart'; | 7 | import '../../common/core/app_config_helper.dart'; |
| 7 | import '../../common/request/dao/system_dao.dart'; | 8 | import '../../common/request/dao/system_dao.dart'; |
| @@ -17,16 +18,10 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { | @@ -17,16 +18,10 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { | ||
| 17 | } | 18 | } |
| 18 | 19 | ||
| 19 | bool exchangeResult = false; | 20 | bool exchangeResult = false; |
| 20 | - late AudioPlayer audioPlayer; | ||
| 21 | - late AudioPlayer studyPlayer; | ||
| 22 | - late AudioPlayer gamePlayer; | ||
| 23 | 21 | ||
| 24 | void _init(InitEvent event, Emitter<HomeState> emit) async { | 22 | void _init(InitEvent event, Emitter<HomeState> emit) async { |
| 25 | if (UserUtil.isLogined()) { | 23 | if (UserUtil.isLogined()) { |
| 26 | - audioPlayer = AudioPlayer(playerId: 'audio'); | ||
| 27 | - gamePlayer = AudioPlayer(playerId: 'game'); | ||
| 28 | - studyPlayer = AudioPlayer(playerId: 'study'); | ||
| 29 | - audioPlayer.play(AssetSource('welcome_to_wow'.assetMp3)); | 24 | + AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.welcomeToWow); |
| 30 | } | 25 | } |
| 31 | await _checkUpdate(emit); | 26 | await _checkUpdate(emit); |
| 32 | } | 27 | } |
lib/pages/home/view.dart
| @@ -12,6 +12,7 @@ import 'package:wow_english/pages/home/state.dart'; | @@ -12,6 +12,7 @@ import 'package:wow_english/pages/home/state.dart'; | ||
| 12 | import 'package:wow_english/pages/home/widgets/BaseHomeHeaderWidget.dart'; | 12 | import 'package:wow_english/pages/home/widgets/BaseHomeHeaderWidget.dart'; |
| 13 | import 'package:wow_english/pages/shop/exchane/bloc/exchange_lesson_bloc.dart'; | 13 | import 'package:wow_english/pages/shop/exchane/bloc/exchange_lesson_bloc.dart'; |
| 14 | import 'package:wow_english/pages/user/bloc/user_bloc.dart'; | 14 | import 'package:wow_english/pages/user/bloc/user_bloc.dart'; |
| 15 | +import 'package:wow_english/utils/audioplayer_util.dart'; | ||
| 15 | 16 | ||
| 16 | import '../../common/core/user_util.dart'; | 17 | import '../../common/core/user_util.dart'; |
| 17 | import '../../common/dialogs/show_dialog.dart'; | 18 | import '../../common/dialogs/show_dialog.dart'; |
| @@ -60,6 +61,8 @@ class _HomePageView extends StatelessWidget { | @@ -60,6 +61,8 @@ class _HomePageView extends StatelessWidget { | ||
| 60 | children: [ | 61 | children: [ |
| 61 | BaseHomeHeaderWidget( | 62 | BaseHomeHeaderWidget( |
| 62 | callBack: (value) => { | 63 | callBack: (value) => { |
| 64 | + AudioPlayerUtil.getInstance() | ||
| 65 | + .playAudio(AudioPlayerUtilType.touch), | ||
| 63 | bloc.exchangeResult = value['exchange'], | 66 | bloc.exchangeResult = value['exchange'], |
| 64 | bloc.add(ExchangeSuccessEvent()) | 67 | bloc.add(ExchangeSuccessEvent()) |
| 65 | }), | 68 | }), |
| @@ -71,8 +74,8 @@ class _HomePageView extends StatelessWidget { | @@ -71,8 +74,8 @@ class _HomePageView extends StatelessWidget { | ||
| 71 | child: GestureDetector( | 74 | child: GestureDetector( |
| 72 | onTap: () { | 75 | onTap: () { |
| 73 | _checkPermission(() { | 76 | _checkPermission(() { |
| 74 | - bloc.studyPlayer | ||
| 75 | - .play(AssetSource('class_time'.assetMp3)); | 77 | + AudioPlayerUtil.getInstance() |
| 78 | + .playAudio(AudioPlayerUtilType.classTime); | ||
| 76 | Future.delayed(const Duration(seconds: 1), () { | 79 | Future.delayed(const Duration(seconds: 1), () { |
| 77 | pushNamed(AppRouteName.courseUnit) | 80 | pushNamed(AppRouteName.courseUnit) |
| 78 | .then((value) => { | 81 | .then((value) => { |
| @@ -108,29 +111,38 @@ class _HomePageView extends StatelessWidget { | @@ -108,29 +111,38 @@ class _HomePageView extends StatelessWidget { | ||
| 108 | ), | 111 | ), |
| 109 | ), | 112 | ), |
| 110 | ), | 113 | ), |
| 111 | - Expanded( | ||
| 112 | - child: BlocBuilder<UserBloc, UserState>( | ||
| 113 | - builder: (context, userState) { | ||
| 114 | - return GestureDetector( | ||
| 115 | - onTap: () { | ||
| 116 | - _checkPermission(() { | ||
| 117 | - Navigator.of(context).pushNamed( | ||
| 118 | - AppRouteName.webView, | ||
| 119 | - arguments: { | ||
| 120 | - 'urlStr': AppConsts.xiaoeShopUrl, | ||
| 121 | - 'webViewTitle': 'Wow精选' | ||
| 122 | - }); | ||
| 123 | - }, bloc); | ||
| 124 | - }, | ||
| 125 | - child: Column( | ||
| 126 | - mainAxisAlignment: MainAxisAlignment.center, | ||
| 127 | - children: [ | ||
| 128 | - Image.asset('xe_shop'.assetPng, | ||
| 129 | - width: 140.5.w, height: 172.h), | ||
| 130 | - 44.verticalSpace | ||
| 131 | - ], | ||
| 132 | - )); | ||
| 133 | - }), | 114 | + Offstage( |
| 115 | + offstage: AppConfigHelper.shouldHidePay() || | ||
| 116 | + !UserUtil.isLogined(), | ||
| 117 | + child: Expanded( | ||
| 118 | + child: BlocBuilder<UserBloc, UserState>( | ||
| 119 | + builder: (context, userState) { | ||
| 120 | + return GestureDetector( | ||
| 121 | + onTap: () { | ||
| 122 | + _checkPermission(() { | ||
| 123 | + AudioPlayerUtil.getInstance().pause(); | ||
| 124 | + Navigator.of(context).pushNamed( | ||
| 125 | + AppRouteName.webView, | ||
| 126 | + arguments: { | ||
| 127 | + 'urlStr': AppConsts.xiaoeShopUrl, | ||
| 128 | + 'webViewTitle': 'Wow精选' | ||
| 129 | + }).then((value) => { | ||
| 130 | + AudioPlayerUtil.getInstance() | ||
| 131 | + .playAudio( | ||
| 132 | + AudioPlayerUtilType.touch), | ||
| 133 | + }); | ||
| 134 | + }, bloc); | ||
| 135 | + }, | ||
| 136 | + child: Column( | ||
| 137 | + mainAxisAlignment: MainAxisAlignment.center, | ||
| 138 | + children: [ | ||
| 139 | + Image.asset('xe_shop'.assetPng, | ||
| 140 | + width: 140.5.w, height: 172.h), | ||
| 141 | + 44.verticalSpace | ||
| 142 | + ], | ||
| 143 | + )); | ||
| 144 | + }), | ||
| 145 | + ), | ||
| 134 | ), | 146 | ), |
| 135 | Expanded( | 147 | Expanded( |
| 136 | child: BlocBuilder<UserBloc, UserState>( | 148 | child: BlocBuilder<UserBloc, UserState>( |
| @@ -138,9 +150,14 @@ class _HomePageView extends StatelessWidget { | @@ -138,9 +150,14 @@ class _HomePageView extends StatelessWidget { | ||
| 138 | return GestureDetector( | 150 | return GestureDetector( |
| 139 | onTap: () { | 151 | onTap: () { |
| 140 | _checkPermission(() { | 152 | _checkPermission(() { |
| 141 | - bloc.gamePlayer.play( | ||
| 142 | - AssetSource('game_time'.assetMp3)); | ||
| 143 | - pushNamed(AppRouteName.games); | 153 | + AudioPlayerUtil.getInstance().playAudio( |
| 154 | + AudioPlayerUtilType.gameTime); | ||
| 155 | + pushNamed(AppRouteName.games) | ||
| 156 | + .then((value) => { | ||
| 157 | + AudioPlayerUtil.getInstance() | ||
| 158 | + .playAudio(AudioPlayerUtilType | ||
| 159 | + .touch), | ||
| 160 | + }); | ||
| 144 | }, bloc); | 161 | }, bloc); |
| 145 | }, | 162 | }, |
| 146 | child: Column( | 163 | child: Column( |
| @@ -189,6 +206,8 @@ class _HomePageView extends StatelessWidget { | @@ -189,6 +206,8 @@ class _HomePageView extends StatelessWidget { | ||
| 189 | }, rightTap: () { | 206 | }, rightTap: () { |
| 190 | popPage(); | 207 | popPage(); |
| 191 | pushNamed(AppRouteName.shop).then((value) { | 208 | pushNamed(AppRouteName.shop).then((value) { |
| 209 | + AudioPlayerUtil.getInstance() | ||
| 210 | + .playAudio(AudioPlayerUtilType.touch); | ||
| 192 | if (value != null) { | 211 | if (value != null) { |
| 193 | bloc.exchangeResult = value['exchange']; | 212 | bloc.exchangeResult = value['exchange']; |
| 194 | bloc.add(ExchangeSuccessEvent()); | 213 | bloc.add(ExchangeSuccessEvent()); |
lib/pages/home/widgets/BaseHomeHeaderWidget.dart
| @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; | @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; | ||
| 3 | import 'package:flutter_screenutil/flutter_screenutil.dart'; | 3 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
| 4 | import 'package:wow_english/common/core/app_config_helper.dart'; | 4 | import 'package:wow_english/common/core/app_config_helper.dart'; |
| 5 | import 'package:wow_english/common/extension/string_extension.dart'; | 5 | import 'package:wow_english/common/extension/string_extension.dart'; |
| 6 | +import 'package:wow_english/utils/audioplayer_util.dart'; | ||
| 6 | 7 | ||
| 7 | import '../../../common/core/user_util.dart'; | 8 | import '../../../common/core/user_util.dart'; |
| 8 | import '../../../models/course_entity.dart'; | 9 | import '../../../models/course_entity.dart'; |
| @@ -84,6 +85,7 @@ class BaseHomeHeaderWidget extends StatelessWidget { | @@ -84,6 +85,7 @@ class BaseHomeHeaderWidget extends StatelessWidget { | ||
| 84 | !UserUtil.isLogined(), | 85 | !UserUtil.isLogined(), |
| 85 | child: GestureDetector( | 86 | child: GestureDetector( |
| 86 | onTap: () => { | 87 | onTap: () => { |
| 88 | + AudioPlayerUtil.getInstance().pause(), | ||
| 87 | pushNamed(AppRouteName.shop).then((value) { | 89 | pushNamed(AppRouteName.shop).then((value) { |
| 88 | if (value != null) { | 90 | if (value != null) { |
| 89 | if (callBack == null) { | 91 | if (callBack == null) { |
| @@ -115,6 +117,7 @@ class BaseHomeHeaderWidget extends StatelessWidget { | @@ -115,6 +117,7 @@ class BaseHomeHeaderWidget extends StatelessWidget { | ||
| 115 | 117 | ||
| 116 | void onUserClick() { | 118 | void onUserClick() { |
| 117 | if (UserUtil.isLogined()) { | 119 | if (UserUtil.isLogined()) { |
| 120 | + AudioPlayerUtil.getInstance().pause(); | ||
| 118 | pushNamed(AppRouteName.user).then((value) { | 121 | pushNamed(AppRouteName.user).then((value) { |
| 119 | if (value != null) { | 122 | if (value != null) { |
| 120 | if (callBack == null) { | 123 | if (callBack == null) { |
lib/pages/section/bloc/section_bloc.dart
| @@ -9,6 +9,7 @@ import 'package:wow_english/common/request/dao/lesson_dao.dart'; | @@ -9,6 +9,7 @@ import 'package:wow_english/common/request/dao/lesson_dao.dart'; | ||
| 9 | import 'package:wow_english/common/request/exception.dart'; | 9 | import 'package:wow_english/common/request/exception.dart'; |
| 10 | import 'package:wow_english/common/request/dao/listen_dao.dart'; | 10 | import 'package:wow_english/common/request/dao/listen_dao.dart'; |
| 11 | import 'package:wow_english/models/course_process_entity.dart'; | 11 | import 'package:wow_english/models/course_process_entity.dart'; |
| 12 | +import 'package:wow_english/utils/audioplayer_util.dart'; | ||
| 12 | import 'package:wow_english/utils/loading.dart'; | 13 | import 'package:wow_english/utils/loading.dart'; |
| 13 | import 'package:wow_english/utils/toast_util.dart'; | 14 | import 'package:wow_english/utils/toast_util.dart'; |
| 14 | 15 | ||
| @@ -45,8 +46,6 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -45,8 +46,6 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
| 45 | ///单元列表是否有刷新,有的话返回上一页时通知其刷新接口数据 | 46 | ///单元列表是否有刷新,有的话返回上一页时通知其刷新接口数据 |
| 46 | bool courseUnitEntityChanged = false; | 47 | bool courseUnitEntityChanged = false; |
| 47 | 48 | ||
| 48 | - late AudioPlayer audioPlayer; // 点击播放器 | ||
| 49 | - late AudioPlayer backgroundPlayer; // 背景播放器 | ||
| 50 | ///courseUnitId与课程环节列表的映射 | 49 | ///courseUnitId与课程环节列表的映射 |
| 51 | final Map<int, List<CourseSectionEntity>?> _courseSectionDatasMap = {}; | 50 | final Map<int, List<CourseSectionEntity>?> _courseSectionDatasMap = {}; |
| 52 | 51 | ||
| @@ -66,25 +65,12 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -66,25 +65,12 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
| 66 | on<RequestVideoLessonEvent>(_requestVideoLesson); | 65 | on<RequestVideoLessonEvent>(_requestVideoLesson); |
| 67 | on<CurrentUnitIndexChangeEvent>(_pageControllerChange); | 66 | on<CurrentUnitIndexChangeEvent>(_pageControllerChange); |
| 68 | on<InitEvent>((event, emit) { | 67 | on<InitEvent>((event, emit) { |
| 69 | - audioPlayer = AudioPlayer(playerId: 'section'); | ||
| 70 | - backgroundPlayer = AudioPlayer(playerId: 'back'); | ||
| 71 | - backgroundPlayer.play(AssetSource('count_with_me_instrumental'.assetMp3)); | ||
| 72 | - | ||
| 73 | - backgroundPlayer.onPlayerStateChanged.listen((event) async { | ||
| 74 | - if (event == PlayerState.completed) { | ||
| 75 | - // 播放结束再次播放 | ||
| 76 | - backgroundPlayer | ||
| 77 | - .play(AssetSource('count_with_me_instrumental'.assetMp3)); | ||
| 78 | - } | ||
| 79 | - }); | 68 | + AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.countWithMe); |
| 80 | }); | 69 | }); |
| 81 | } | 70 | } |
| 82 | @override | 71 | @override |
| 83 | Future<void> close() { | 72 | Future<void> close() { |
| 84 | - audioPlayer.release(); | ||
| 85 | - audioPlayer.dispose(); | ||
| 86 | - backgroundPlayer.release(); | ||
| 87 | - backgroundPlayer.dispose(); | 73 | + AudioPlayerUtil.getInstance().pause(); |
| 88 | return super.close(); | 74 | return super.close(); |
| 89 | } | 75 | } |
| 90 | 76 |
lib/pages/section/bloc/section_state.dart
| @@ -22,5 +22,3 @@ class RequestEnterClassState extends SectionState { | @@ -22,5 +22,3 @@ class RequestEnterClassState extends SectionState { | ||
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | class CurrentPageIndexState extends SectionState {} | 24 | class CurrentPageIndexState extends SectionState {} |
| 25 | - | ||
| 26 | -class VoicePlayChangeState extends SectionState {} |
lib/pages/section/section_page.dart
| @@ -12,6 +12,8 @@ import 'package:wow_english/pages/section/widgets/section_item.dart'; | @@ -12,6 +12,8 @@ import 'package:wow_english/pages/section/widgets/section_item.dart'; | ||
| 12 | import 'package:wow_english/pages/section/widgets/section_bouns_item.dart'; | 12 | import 'package:wow_english/pages/section/widgets/section_bouns_item.dart'; |
| 13 | import 'package:wow_english/pages/section/widgets/section_header_widget.dart'; | 13 | import 'package:wow_english/pages/section/widgets/section_header_widget.dart'; |
| 14 | import 'package:wow_english/route/route.dart'; | 14 | import 'package:wow_english/route/route.dart'; |
| 15 | +import 'package:wow_english/utils/audioplayer_util.dart'; | ||
| 16 | +import 'package:wow_english/utils/log_util.dart'; | ||
| 15 | import 'package:wow_english/utils/toast_util.dart'; | 17 | import 'package:wow_english/utils/toast_util.dart'; |
| 16 | 18 | ||
| 17 | import '../../models/course_section_entity.dart'; | 19 | import '../../models/course_section_entity.dart'; |
| @@ -89,23 +91,23 @@ class _SectionPageView extends StatelessWidget { | @@ -89,23 +91,23 @@ class _SectionPageView extends StatelessWidget { | ||
| 89 | currentTime: dataMap['currentTime'], | 91 | currentTime: dataMap['currentTime'], |
| 90 | autoNextSection: dataMap['nextSection'])); | 92 | autoNextSection: dataMap['nextSection'])); |
| 91 | } | 93 | } |
| 92 | - if (bloc.backgroundPlayer.state == PlayerState.paused) { | ||
| 93 | - bloc.backgroundPlayer.resume(); | ||
| 94 | - } | 94 | + AudioPlayerUtil.getInstance() |
| 95 | + .playAudio(AudioPlayerUtilType.countWithMe); | ||
| 95 | }); | 96 | }); |
| 96 | return; | 97 | return; |
| 97 | } | 98 | } |
| 98 | 99 | ||
| 99 | if (state is RequestEnterClassState) { | 100 | if (state is RequestEnterClassState) { |
| 100 | - bloc.backgroundPlayer.pause(); | ||
| 101 | if (state.courseType != SectionType.practice.value && | 101 | if (state.courseType != SectionType.practice.value && |
| 102 | state.courseType != SectionType.pictureBook.value) { | 102 | state.courseType != SectionType.pictureBook.value) { |
| 103 | ///视频类型 | 103 | ///视频类型 |
| 104 | ///获取视频课程内容 | 104 | ///获取视频课程内容 |
| 105 | if (state.courseType == 1) { | 105 | if (state.courseType == 1) { |
| 106 | - bloc.audioPlayer.play(AssetSource('music_time'.assetMp3)); | 106 | + AudioPlayerUtil.getInstance() |
| 107 | + .playAudio(AudioPlayerUtilType.musicTime); | ||
| 107 | } else { | 108 | } else { |
| 108 | - bloc.audioPlayer.play(AssetSource('video_time'.assetMp3)); | 109 | + AudioPlayerUtil.getInstance() |
| 110 | + .playAudio(AudioPlayerUtilType.videoTime); | ||
| 109 | } | 111 | } |
| 110 | Future.delayed(const Duration(seconds: 1), () { | 112 | Future.delayed(const Duration(seconds: 1), () { |
| 111 | bloc.add(RequestVideoLessonEvent( | 113 | bloc.add(RequestVideoLessonEvent( |
| @@ -116,7 +118,8 @@ class _SectionPageView extends StatelessWidget { | @@ -116,7 +118,8 @@ class _SectionPageView extends StatelessWidget { | ||
| 116 | } | 118 | } |
| 117 | 119 | ||
| 118 | if (state.courseType == SectionType.pictureBook.value) { | 120 | if (state.courseType == SectionType.pictureBook.value) { |
| 119 | - bloc.audioPlayer.play(AssetSource('reading_time'.assetMp3)); | 121 | + AudioPlayerUtil.getInstance() |
| 122 | + .playAudio(AudioPlayerUtilType.readingTime); | ||
| 120 | Future.delayed(const Duration(seconds: 1), () { | 123 | Future.delayed(const Duration(seconds: 1), () { |
| 121 | //绘本 | 124 | //绘本 |
| 122 | pushNamed(AppRouteName.reading, | 125 | pushNamed(AppRouteName.reading, |
| @@ -130,9 +133,8 @@ class _SectionPageView extends StatelessWidget { | @@ -130,9 +133,8 @@ class _SectionPageView extends StatelessWidget { | ||
| 130 | currentStep: dataMap['currentStep'], | 133 | currentStep: dataMap['currentStep'], |
| 131 | autoNextSection: dataMap['nextSection'], | 134 | autoNextSection: dataMap['nextSection'], |
| 132 | )); | 135 | )); |
| 133 | - if (bloc.backgroundPlayer.state == PlayerState.paused) { | ||
| 134 | - bloc.backgroundPlayer.resume(); | ||
| 135 | - } | 136 | + AudioPlayerUtil.getInstance() |
| 137 | + .playAudio(AudioPlayerUtilType.countWithMe); | ||
| 136 | } | 138 | } |
| 137 | }); | 139 | }); |
| 138 | }); | 140 | }); |
| @@ -142,7 +144,8 @@ class _SectionPageView extends StatelessWidget { | @@ -142,7 +144,8 @@ class _SectionPageView extends StatelessWidget { | ||
| 142 | 144 | ||
| 143 | if (state.courseType == SectionType.practice.value) { | 145 | if (state.courseType == SectionType.practice.value) { |
| 144 | //练习 | 146 | //练习 |
| 145 | - bloc.audioPlayer.play(AssetSource('quiz_time'.assetMp3)); | 147 | + AudioPlayerUtil.getInstance() |
| 148 | + .playAudio(AudioPlayerUtilType.quizTime); | ||
| 146 | Future.delayed(const Duration(seconds: 1), () { | 149 | Future.delayed(const Duration(seconds: 1), () { |
| 147 | pushNamed(AppRouteName.topicPic, | 150 | pushNamed(AppRouteName.topicPic, |
| 148 | arguments: {'courseLessonId': state.courseLessonId}) | 151 | arguments: {'courseLessonId': state.courseLessonId}) |
| @@ -154,9 +157,8 @@ class _SectionPageView extends StatelessWidget { | @@ -154,9 +157,8 @@ class _SectionPageView extends StatelessWidget { | ||
| 154 | currentStep: dataMap['currentStep'], | 157 | currentStep: dataMap['currentStep'], |
| 155 | autoNextSection: dataMap['nextSection'])); | 158 | autoNextSection: dataMap['nextSection'])); |
| 156 | } | 159 | } |
| 157 | - if (bloc.backgroundPlayer.state == PlayerState.paused) { | ||
| 158 | - bloc.backgroundPlayer.resume(); | ||
| 159 | - } | 160 | + AudioPlayerUtil.getInstance() |
| 161 | + .playAudio(AudioPlayerUtilType.countWithMe); | ||
| 160 | }); | 162 | }); |
| 161 | }); | 163 | }); |
| 162 | return; | 164 | return; |
lib/pages/unit/bloc.dart
| 1 | import 'package:bloc/bloc.dart'; | 1 | import 'package:bloc/bloc.dart'; |
| 2 | import 'package:wow_english/pages/unit/widget/home_tab_header_widget.dart'; | 2 | import 'package:wow_english/pages/unit/widget/home_tab_header_widget.dart'; |
| 3 | +import 'package:wow_english/utils/audioplayer_util.dart'; | ||
| 3 | 4 | ||
| 4 | import '../../common/request/dao/lesson_dao.dart'; | 5 | import '../../common/request/dao/lesson_dao.dart'; |
| 5 | import '../../common/request/exception.dart'; | 6 | import '../../common/request/exception.dart'; |
| @@ -24,6 +25,9 @@ class UnitBloc extends Bloc<UnitEvent, UnitState> { | @@ -24,6 +25,9 @@ class UnitBloc extends Bloc<UnitEvent, UnitState> { | ||
| 24 | 25 | ||
| 25 | UnitBloc(CourseModuleEntity? courseEntity) : super(UnitState().init()) { | 26 | UnitBloc(CourseModuleEntity? courseEntity) : super(UnitState().init()) { |
| 26 | on<RequestUnitDataEvent>(_requestUnitDatas); | 27 | on<RequestUnitDataEvent>(_requestUnitDatas); |
| 28 | + on<UnitInitEvent>((event, emit) { | ||
| 29 | + AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.inMyTummy); | ||
| 30 | + }); | ||
| 27 | } | 31 | } |
| 28 | 32 | ||
| 29 | void _requestUnitDatas( | 33 | void _requestUnitDatas( |
| @@ -45,15 +49,26 @@ class UnitBloc extends Bloc<UnitEvent, UnitState> { | @@ -45,15 +49,26 @@ class UnitBloc extends Bloc<UnitEvent, UnitState> { | ||
| 45 | } | 49 | } |
| 46 | 50 | ||
| 47 | void headerActionEvent(HeaderActionType type) { | 51 | void headerActionEvent(HeaderActionType type) { |
| 52 | + AudioPlayerUtil.getInstance().pause(); | ||
| 48 | if (type == HeaderActionType.video) { | 53 | if (type == HeaderActionType.video) { |
| 49 | pushNamed(AppRouteName.reAfter); | 54 | pushNamed(AppRouteName.reAfter); |
| 50 | } else if (type == HeaderActionType.phase) { | 55 | } else if (type == HeaderActionType.phase) { |
| 51 | - pushNamed(AppRouteName.courseModule); | 56 | + pushNamed(AppRouteName.courseModule).then((value) => { |
| 57 | + AudioPlayerUtil.getInstance() | ||
| 58 | + .playAudio(AudioPlayerUtilType.inMyTummy) | ||
| 59 | + }); | ||
| 60 | + ; | ||
| 52 | } else if (type == HeaderActionType.listen) { | 61 | } else if (type == HeaderActionType.listen) { |
| 53 | - pushNamed(AppRouteName.listen); | 62 | + pushNamed(AppRouteName.listen).then((value) => { |
| 63 | + AudioPlayerUtil.getInstance() | ||
| 64 | + .playAudio(AudioPlayerUtilType.inMyTummy) | ||
| 65 | + }); | ||
| 54 | } else if (type == HeaderActionType.shop) { | 66 | } else if (type == HeaderActionType.shop) { |
| 55 | - pushNamed(AppRouteName.shop) | ||
| 56 | - .then((value) => {exchangeResult = value['exchange']}); | 67 | + pushNamed(AppRouteName.shop).then((value) => { |
| 68 | + AudioPlayerUtil.getInstance() | ||
| 69 | + .playAudio(AudioPlayerUtilType.inMyTummy), | ||
| 70 | + exchangeResult = value['exchange'] | ||
| 71 | + }); | ||
| 57 | } else if (type == HeaderActionType.user) { | 72 | } else if (type == HeaderActionType.user) { |
| 58 | pushNamed(AppRouteName.user); | 73 | pushNamed(AppRouteName.user); |
| 59 | } | 74 | } |
lib/pages/unit/event.dart
lib/pages/unit/view.dart
| @@ -5,6 +5,7 @@ import 'package:wow_english/pages/unit/state.dart'; | @@ -5,6 +5,7 @@ import 'package:wow_english/pages/unit/state.dart'; | ||
| 5 | import 'package:wow_english/pages/unit/widget/course_unit_item.dart'; | 5 | import 'package:wow_english/pages/unit/widget/course_unit_item.dart'; |
| 6 | import 'package:wow_english/pages/unit/widget/home_tab_header_widget.dart'; | 6 | import 'package:wow_english/pages/unit/widget/home_tab_header_widget.dart'; |
| 7 | import 'package:wow_english/route/route.dart'; | 7 | import 'package:wow_english/route/route.dart'; |
| 8 | +import 'package:wow_english/utils/audioplayer_util.dart'; | ||
| 8 | 9 | ||
| 9 | import '../../models/course_module_entity.dart'; | 10 | import '../../models/course_module_entity.dart'; |
| 10 | import '../../models/course_unit_entity.dart'; | 11 | import '../../models/course_unit_entity.dart'; |
| @@ -23,6 +24,7 @@ class UnitPage extends StatelessWidget { | @@ -23,6 +24,7 @@ class UnitPage extends StatelessWidget { | ||
| 23 | Widget build(BuildContext context) { | 24 | Widget build(BuildContext context) { |
| 24 | return BlocProvider( | 25 | return BlocProvider( |
| 25 | create: (BuildContext context) => UnitBloc(courseModuleEntity) | 26 | create: (BuildContext context) => UnitBloc(courseModuleEntity) |
| 27 | + ..add(UnitInitEvent()) | ||
| 26 | ..add(RequestUnitDataEvent(courseModuleEntity?.id)), | 28 | ..add(RequestUnitDataEvent(courseModuleEntity?.id)), |
| 27 | child: Builder(builder: (context) => _buildPage(context)), | 29 | child: Builder(builder: (context) => _buildPage(context)), |
| 28 | ); | 30 | ); |
| @@ -41,6 +43,8 @@ class UnitPage extends StatelessWidget { | @@ -41,6 +43,8 @@ class UnitPage extends StatelessWidget { | ||
| 41 | HomeTabHeaderWidget( | 43 | HomeTabHeaderWidget( |
| 42 | courseModuleCode: bloc.getCourseModuleCode(), | 44 | courseModuleCode: bloc.getCourseModuleCode(), |
| 43 | onBack: () { | 45 | onBack: () { |
| 46 | + AudioPlayerUtil.getInstance() | ||
| 47 | + .playAudio(AudioPlayerUtilType.touch); | ||
| 44 | popPage(data: {'exchange': bloc.exchangeResult}); | 48 | popPage(data: {'exchange': bloc.exchangeResult}); |
| 45 | }, | 49 | }, |
| 46 | actionTap: (HeaderActionType type) { | 50 | actionTap: (HeaderActionType type) { |
| @@ -63,12 +67,14 @@ class UnitPage extends StatelessWidget { | @@ -63,12 +67,14 @@ class UnitPage extends StatelessWidget { | ||
| 63 | showToast('当前单元课程暂未解锁'); | 67 | showToast('当前单元课程暂未解锁'); |
| 64 | return; | 68 | return; |
| 65 | } | 69 | } |
| 66 | - | 70 | + AudioPlayerUtil.getInstance().pause(); |
| 67 | pushNamed(AppRouteName.courseSection, | 71 | pushNamed(AppRouteName.courseSection, |
| 68 | arguments: { | 72 | arguments: { |
| 69 | 'courseUnitEntity': bloc.unitData, | 73 | 'courseUnitEntity': bloc.unitData, |
| 70 | 'courseUnitId': data.id | 74 | 'courseUnitId': data.id |
| 71 | }).then((value) { | 75 | }).then((value) { |
| 76 | + AudioPlayerUtil.getInstance() | ||
| 77 | + .playAudio(AudioPlayerUtilType.inMyTummy); | ||
| 72 | if (value != null) { | 78 | if (value != null) { |
| 73 | Map<String, dynamic> dataMap = | 79 | Map<String, dynamic> dataMap = |
| 74 | value as Map<String, dynamic>; | 80 | value as Map<String, dynamic>; |
lib/utils/audioplayer_util.dart
0 → 100644
| 1 | +import 'package:audioplayers/audioplayers.dart'; | ||
| 2 | +import 'package:wow_english/common/extension/string_extension.dart'; | ||
| 3 | + | ||
| 4 | +enum AudioPlayerUtilType { | ||
| 5 | + welcomeToWow('welcome_to_wow'), | ||
| 6 | + classTime('class_time'), | ||
| 7 | + gameTime('game_time'), | ||
| 8 | + musicTime('music_time'), | ||
| 9 | + readingTime('reading_time'), | ||
| 10 | + videoTime('video_time'), | ||
| 11 | + quizTime('quiz_time'), | ||
| 12 | + countWithMe('count_with_me_instrumental'), | ||
| 13 | + inMyTummy('in_my_tummy_instrumental'), | ||
| 14 | + touch('touch_instrumental'); | ||
| 15 | + | ||
| 16 | + const AudioPlayerUtilType(this.path); | ||
| 17 | + | ||
| 18 | + final String path; | ||
| 19 | +} | ||
| 20 | + | ||
| 21 | +class AudioPlayerUtil { | ||
| 22 | + static AudioPlayerUtil? _instance; | ||
| 23 | + late AudioPlayer audioPlayer; | ||
| 24 | + late AudioPlayerUtilType currentType; | ||
| 25 | + | ||
| 26 | + // 私有构造函数 | ||
| 27 | + AudioPlayerUtil._internal() { | ||
| 28 | + audioPlayer = AudioPlayer(); | ||
| 29 | + audioPlayer.onPlayerStateChanged.listen((event) async { | ||
| 30 | + if (event == PlayerState.completed) { | ||
| 31 | + // 播放结束再次播放 | ||
| 32 | + if (currentType == AudioPlayerUtilType.inMyTummy) { | ||
| 33 | + AudioPlayerUtil.getInstance() | ||
| 34 | + .playAudio(AudioPlayerUtilType.inMyTummy); | ||
| 35 | + } | ||
| 36 | + if (currentType == AudioPlayerUtilType.countWithMe) { | ||
| 37 | + AudioPlayerUtil.getInstance() | ||
| 38 | + .playAudio(AudioPlayerUtilType.countWithMe); | ||
| 39 | + } | ||
| 40 | + if (currentType == AudioPlayerUtilType.welcomeToWow) { | ||
| 41 | + AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.touch); | ||
| 42 | + } | ||
| 43 | + if (currentType == AudioPlayerUtilType.touch) { | ||
| 44 | + AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.touch); | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + }); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + static AudioPlayerUtil getInstance() { | ||
| 51 | + _instance ??= AudioPlayerUtil._internal(); | ||
| 52 | + return _instance!; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | +// 播放音频 | ||
| 56 | + Future<void> playAudio(AudioPlayerUtilType type) async { | ||
| 57 | + currentType = type; | ||
| 58 | + String path = type.path; | ||
| 59 | + await audioPlayer.play(AssetSource(path.assetMp3), volume: 0.5); | ||
| 60 | + await audioPlayer.onPlayerComplete.first; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + // stop | ||
| 64 | + void stop() { | ||
| 65 | + audioPlayer.stop(); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + // pause | ||
| 69 | + void pause() { | ||
| 70 | + if (audioPlayer.state == PlayerState.playing) { | ||
| 71 | + audioPlayer.pause(); | ||
| 72 | + } | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + // resume | ||
| 76 | + void resume() { | ||
| 77 | + if (audioPlayer.state == PlayerState.paused) { | ||
| 78 | + audioPlayer.resume(); | ||
| 79 | + } | ||
| 80 | + } | ||
| 81 | +} |