Commit 2d1ead5369e419d9e972ead8b9373a0ba058d276
1 parent
9e29ffea
feat:背景音播放优化
Showing
8 changed files
with
104 additions
and
85 deletions
lib/pages/home/bloc.dart
| @@ -44,7 +44,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { | @@ -44,7 +44,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { | ||
| 44 | return; | 44 | return; |
| 45 | } | 45 | } |
| 46 | Log.d( | 46 | Log.d( |
| 47 | - "WQF _checkUpdate appVersionEntity: $appVersionEntity localVersion=$localVersion"); | 47 | + "HomeBloc _checkUpdate appVersionEntity: $appVersionEntity localVersion=$localVersion"); |
| 48 | if (localVersion < int.parse(appVersionEntity.version ?? '0')) { | 48 | if (localVersion < int.parse(appVersionEntity.version ?? '0')) { |
| 49 | emit(UpdateDialogState( | 49 | emit(UpdateDialogState( |
| 50 | appVersionEntity.volType == UpdateStrategy.FORCE.name, | 50 | appVersionEntity.volType == UpdateStrategy.FORCE.name, |
lib/pages/home/view.dart
| @@ -60,8 +60,8 @@ class _HomePageView extends StatelessWidget { | @@ -60,8 +60,8 @@ class _HomePageView extends StatelessWidget { | ||
| 60 | child: Column( | 60 | child: Column( |
| 61 | children: [ | 61 | children: [ |
| 62 | BaseHomeHeaderWidget( | 62 | BaseHomeHeaderWidget( |
| 63 | - callBack: (value) => { | ||
| 64 | - AudioPlayerUtil.getInstance() | 63 | + callBack: (value) async => { |
| 64 | + await AudioPlayerUtil.getInstance() | ||
| 65 | .playAudio(AudioPlayerUtilType.touch), | 65 | .playAudio(AudioPlayerUtilType.touch), |
| 66 | bloc.exchangeResult = value['exchange'], | 66 | bloc.exchangeResult = value['exchange'], |
| 67 | bloc.add(ExchangeSuccessEvent()) | 67 | bloc.add(ExchangeSuccessEvent()) |
| @@ -113,15 +113,15 @@ class _HomePageView extends StatelessWidget { | @@ -113,15 +113,15 @@ class _HomePageView extends StatelessWidget { | ||
| 113 | builder: (context, userState) { | 113 | builder: (context, userState) { |
| 114 | return GestureDetector( | 114 | return GestureDetector( |
| 115 | onTap: () { | 115 | onTap: () { |
| 116 | - _checkPermission(() { | ||
| 117 | - AudioPlayerUtil.getInstance().pause(); | 116 | + _checkPermission(() async { |
| 117 | + await AudioPlayerUtil.getInstance().pause(); | ||
| 118 | Navigator.of(context).pushNamed( | 118 | Navigator.of(context).pushNamed( |
| 119 | AppRouteName.webView, | 119 | AppRouteName.webView, |
| 120 | arguments: { | 120 | arguments: { |
| 121 | 'urlStr': AppConsts.xiaoeShopUrl, | 121 | 'urlStr': AppConsts.xiaoeShopUrl, |
| 122 | 'webViewTitle': 'Wow精选' | 122 | 'webViewTitle': 'Wow精选' |
| 123 | - }).then((value) => { | ||
| 124 | - AudioPlayerUtil.getInstance().playAudio( | 123 | + }).then((value) async => { |
| 124 | + await AudioPlayerUtil.getInstance().playAudio( | ||
| 125 | AudioPlayerUtilType.touch), | 125 | AudioPlayerUtilType.touch), |
| 126 | }); | 126 | }); |
| 127 | }, bloc); | 127 | }, bloc); |
lib/pages/home/widgets/BaseHomeHeaderWidget.dart
| @@ -84,8 +84,8 @@ class BaseHomeHeaderWidget extends StatelessWidget { | @@ -84,8 +84,8 @@ class BaseHomeHeaderWidget extends StatelessWidget { | ||
| 84 | offstage: AppConfigHelper.shouldHidePay() || | 84 | offstage: AppConfigHelper.shouldHidePay() || |
| 85 | !UserUtil.isLogined(), | 85 | !UserUtil.isLogined(), |
| 86 | child: GestureDetector( | 86 | child: GestureDetector( |
| 87 | - onTap: () => { | ||
| 88 | - AudioPlayerUtil.getInstance().pause(), | 87 | + onTap: () async => { |
| 88 | + await AudioPlayerUtil.getInstance().pause(), | ||
| 89 | pushNamed(AppRouteName.shop).then((value) { | 89 | pushNamed(AppRouteName.shop).then((value) { |
| 90 | if (value != null) { | 90 | if (value != null) { |
| 91 | if (callBack == null) { | 91 | if (callBack == null) { |
| @@ -115,9 +115,9 @@ class BaseHomeHeaderWidget extends StatelessWidget { | @@ -115,9 +115,9 @@ class BaseHomeHeaderWidget extends StatelessWidget { | ||
| 115 | ); | 115 | ); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | - void onUserClick() { | 118 | + Future<void> onUserClick() async { |
| 119 | if (UserUtil.isLogined()) { | 119 | if (UserUtil.isLogined()) { |
| 120 | - AudioPlayerUtil.getInstance().pause(); | 120 | + await AudioPlayerUtil.getInstance().pause(); |
| 121 | pushNamed(AppRouteName.user).then((value) { | 121 | pushNamed(AppRouteName.user).then((value) { |
| 122 | if (value != null) { | 122 | if (value != null) { |
| 123 | if (callBack == null) { | 123 | if (callBack == null) { |
lib/pages/section/bloc/section_bloc.dart
| @@ -64,15 +64,10 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -64,15 +64,10 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
| 64 | on<RequestEnterClassEvent>(_requestEnterClass); | 64 | on<RequestEnterClassEvent>(_requestEnterClass); |
| 65 | on<RequestVideoLessonEvent>(_requestVideoLesson); | 65 | on<RequestVideoLessonEvent>(_requestVideoLesson); |
| 66 | on<CurrentUnitIndexChangeEvent>(_pageControllerChange); | 66 | on<CurrentUnitIndexChangeEvent>(_pageControllerChange); |
| 67 | - on<InitEvent>((event, emit) { | ||
| 68 | - AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.countWithMe); | 67 | + on<InitEvent>((event, emit) async { |
| 68 | + await AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.countWithMe); | ||
| 69 | }); | 69 | }); |
| 70 | } | 70 | } |
| 71 | - @override | ||
| 72 | - Future<void> close() { | ||
| 73 | - AudioPlayerUtil.getInstance().pause(); | ||
| 74 | - return super.close(); | ||
| 75 | - } | ||
| 76 | 71 | ||
| 77 | void _requestSectionsData( | 72 | void _requestSectionsData( |
| 78 | RequestDataEvent event, Emitter<SectionState> emitter) async { | 73 | RequestDataEvent event, Emitter<SectionState> emitter) async { |
lib/pages/unit/bloc.dart
| @@ -48,9 +48,10 @@ class UnitBloc extends Bloc<UnitEvent, UnitState> { | @@ -48,9 +48,10 @@ class UnitBloc extends Bloc<UnitEvent, UnitState> { | ||
| 48 | return _moduleEntity?.code ?? _unitData?.courseModuleCode; | 48 | return _moduleEntity?.code ?? _unitData?.courseModuleCode; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | - void headerActionEvent(HeaderActionType type) { | ||
| 52 | - AudioPlayerUtil.getInstance().pause(); | 51 | + Future<void> headerActionEvent(HeaderActionType type) async { |
| 52 | + await AudioPlayerUtil.getInstance().pause(); | ||
| 53 | if (type == HeaderActionType.video) { | 53 | if (type == HeaderActionType.video) { |
| 54 | + //视频跟读暂时隐藏了 | ||
| 54 | pushNamed(AppRouteName.reAfter); | 55 | pushNamed(AppRouteName.reAfter); |
| 55 | } else if (type == HeaderActionType.phase) { | 56 | } else if (type == HeaderActionType.phase) { |
| 56 | pushNamed(AppRouteName.courseModule).then((value) => { | 57 | pushNamed(AppRouteName.courseModule).then((value) => { |
lib/pages/unit/view.dart
| @@ -62,12 +62,12 @@ class UnitPage extends StatelessWidget { | @@ -62,12 +62,12 @@ class UnitPage extends StatelessWidget { | ||
| 62 | CourseUnitDetail? data = | 62 | CourseUnitDetail? data = |
| 63 | bloc.unitData?.courseUnitVOList?[index]; | 63 | bloc.unitData?.courseUnitVOList?[index]; |
| 64 | return GestureDetector( | 64 | return GestureDetector( |
| 65 | - onTap: () { | 65 | + onTap: () async { |
| 66 | if (data.lock == true) { | 66 | if (data.lock == true) { |
| 67 | showToast('当前单元课程暂未解锁'); | 67 | showToast('当前单元课程暂未解锁'); |
| 68 | return; | 68 | return; |
| 69 | } | 69 | } |
| 70 | - AudioPlayerUtil.getInstance().pause(); | 70 | + // await AudioPlayerUtil.getInstance().pause(); |
| 71 | pushNamed(AppRouteName.courseSection, | 71 | pushNamed(AppRouteName.courseSection, |
| 72 | arguments: { | 72 | arguments: { |
| 73 | 'courseUnitEntity': bloc.unitData, | 73 | 'courseUnitEntity': bloc.unitData, |
lib/pages/user/setting/reback_page.dart
| @@ -26,73 +26,87 @@ class ReBackPageState extends State<ReBackPage> { | @@ -26,73 +26,87 @@ class ReBackPageState extends State<ReBackPage> { | ||
| 26 | @override | 26 | @override |
| 27 | Widget build(BuildContext context) { | 27 | Widget build(BuildContext context) { |
| 28 | return Scaffold( | 28 | return Scaffold( |
| 29 | - appBar: const WEAppBar( | ||
| 30 | - titleText: '我要反馈', | ||
| 31 | - ), | ||
| 32 | - body: Container( | ||
| 33 | - color: Colors.white, | ||
| 34 | - padding: EdgeInsets.symmetric( | ||
| 35 | - horizontal: 24.w | 29 | + appBar: const WEAppBar( |
| 30 | + titleText: '我要反馈', | ||
| 36 | ), | 31 | ), |
| 37 | - child: SafeArea( | ||
| 38 | - child: Column( | ||
| 39 | - children: [ | ||
| 40 | - 20.verticalSpace, | ||
| 41 | - Row( | ||
| 42 | - mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||
| 43 | - children: [ | ||
| 44 | - Text( | ||
| 45 | - '请输入您要反馈的问题和意见,10-500个字', | ||
| 46 | - textAlign: TextAlign.left, | ||
| 47 | - style: TextStyle( | ||
| 48 | - fontSize: 19.sp, | ||
| 49 | - color: HexColor('#333333') | ||
| 50 | - ), | ||
| 51 | - ), | ||
| 52 | - Text( | ||
| 53 | - '48/500', | ||
| 54 | - textAlign: TextAlign.right, | ||
| 55 | - style: TextStyle( | ||
| 56 | - fontSize: 19.sp, | ||
| 57 | - color: HexColor('#333333') | ||
| 58 | - ),) | ||
| 59 | - ], | ||
| 60 | - ), | ||
| 61 | - 9.5.verticalSpace, | ||
| 62 | - Expanded( | ||
| 63 | - child: Container( | ||
| 64 | - decoration: BoxDecoration( | ||
| 65 | - image: DecorationImage( | ||
| 66 | - fit: BoxFit.fill, | ||
| 67 | - image: AssetImage('bg_reback'.assetPng) | 32 | + body: Container( |
| 33 | + color: Colors.white, | ||
| 34 | + padding: EdgeInsets.symmetric(horizontal: 10.w), | ||
| 35 | + child: SafeArea( | ||
| 36 | + child: LayoutBuilder(builder: (context, constraints) { | ||
| 37 | + return SingleChildScrollView( | ||
| 38 | + child: ConstrainedBox( | ||
| 39 | + constraints: BoxConstraints( | ||
| 40 | + minHeight: constraints.maxHeight, | ||
| 41 | + ), | ||
| 42 | + child: IntrinsicHeight( | ||
| 43 | + child: Column( | ||
| 44 | + children: [ | ||
| 45 | + 20.verticalSpace, | ||
| 46 | + Row( | ||
| 47 | + mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||
| 48 | + children: [ | ||
| 49 | + Text( | ||
| 50 | + '请输入您要反馈的问题和意见,10-500个字', | ||
| 51 | + textAlign: TextAlign.left, | ||
| 52 | + style: TextStyle( | ||
| 53 | + fontSize: 19.sp, color: HexColor('#333333')), | ||
| 54 | + ), | ||
| 55 | + Text( | ||
| 56 | + '48/500', | ||
| 57 | + textAlign: TextAlign.right, | ||
| 58 | + style: TextStyle( | ||
| 59 | + fontSize: 19.sp, color: HexColor('#333333')), | ||
| 60 | + ) | ||
| 61 | + ], | ||
| 62 | + ), | ||
| 63 | + 9.5.verticalSpace, | ||
| 64 | + Expanded( | ||
| 65 | + child: Container( | ||
| 66 | + decoration: BoxDecoration( | ||
| 67 | + image: DecorationImage( | ||
| 68 | + image: AssetImage('bg_reback'.assetPng), | ||
| 69 | + fit: BoxFit.fill)), | ||
| 70 | + child: Padding( | ||
| 71 | + padding: const EdgeInsets.symmetric( | ||
| 72 | + vertical: 10, horizontal: 16), | ||
| 73 | + // 设置对称内边距 | ||
| 74 | + child: TextField( | ||
| 75 | + textInputAction: TextInputAction.done, | ||
| 76 | + decoration: InputDecoration( | ||
| 77 | + border: InputBorder.none, | ||
| 78 | + hintStyle: TextStyle( | ||
| 79 | + fontSize: 16.sp, | ||
| 80 | + color: const Color(0xFF999999))), | ||
| 81 | + ), | ||
| 82 | + ), | ||
| 83 | + ), | ||
| 84 | + ), | ||
| 85 | + 4.5.verticalSpace, | ||
| 86 | + Container( | ||
| 87 | + decoration: BoxDecoration( | ||
| 88 | + image: DecorationImage( | ||
| 89 | + fit: BoxFit.fill, | ||
| 90 | + image: AssetImage(_canEnsure | ||
| 91 | + ? 're_button'.assetPng | ||
| 92 | + : 're_button_dis'.assetPng))), | ||
| 93 | + alignment: Alignment.center, | ||
| 94 | + width: 91.w, | ||
| 95 | + height: 45.h, | ||
| 96 | + child: Text( | ||
| 97 | + '提交', | ||
| 98 | + textAlign: TextAlign.center, | ||
| 99 | + style: | ||
| 100 | + TextStyle(color: Colors.white, fontSize: 17.sp), | ||
| 101 | + ), | ||
| 68 | ) | 102 | ) |
| 103 | + ], | ||
| 69 | ), | 104 | ), |
| 70 | ), | 105 | ), |
| 71 | ), | 106 | ), |
| 72 | - 4.5.verticalSpace, | ||
| 73 | - Container( | ||
| 74 | - decoration: BoxDecoration( | ||
| 75 | - image: DecorationImage( | ||
| 76 | - fit: BoxFit.fill, | ||
| 77 | - image: AssetImage(_canEnsure?'re_button'.assetPng:'re_button_dis'.assetPng) | ||
| 78 | - ) | ||
| 79 | - ), | ||
| 80 | - alignment: Alignment.center, | ||
| 81 | - width: 91.w, | ||
| 82 | - height: 45.h, | ||
| 83 | - child: Text( | ||
| 84 | - '提交', | ||
| 85 | - textAlign: TextAlign.center, | ||
| 86 | - style: TextStyle( | ||
| 87 | - color: Colors.white, | ||
| 88 | - fontSize: 17.sp | ||
| 89 | - ), | ||
| 90 | - ), | ||
| 91 | - ) | ||
| 92 | - ], | ||
| 93 | - ), | 107 | + ); |
| 108 | + }), | ||
| 94 | ), | 109 | ), |
| 95 | - ) | ||
| 96 | - ); | 110 | + )); |
| 97 | } | 111 | } |
| 98 | -} | ||
| 99 | \ No newline at end of file | 112 | \ No newline at end of file |
| 113 | +} |
lib/utils/audio_player_util.dart
| @@ -2,6 +2,8 @@ import 'package:audioplayers/audioplayers.dart'; | @@ -2,6 +2,8 @@ import 'package:audioplayers/audioplayers.dart'; | ||
| 2 | import 'package:flutter/cupertino.dart'; | 2 | import 'package:flutter/cupertino.dart'; |
| 3 | import 'package:wow_english/common/extension/string_extension.dart'; | 3 | import 'package:wow_english/common/extension/string_extension.dart'; |
| 4 | 4 | ||
| 5 | +import 'log_util.dart'; | ||
| 6 | + | ||
| 5 | enum AudioPlayerUtilType { | 7 | enum AudioPlayerUtilType { |
| 6 | welcomeToWow('welcome_to_wow'), | 8 | welcomeToWow('welcome_to_wow'), |
| 7 | classTime('class_time'), | 9 | classTime('class_time'), |
| @@ -24,6 +26,7 @@ class AudioPlayerUtil extends WidgetsBindingObserver { | @@ -24,6 +26,7 @@ class AudioPlayerUtil extends WidgetsBindingObserver { | ||
| 24 | late AudioPlayer _audioPlayer; | 26 | late AudioPlayer _audioPlayer; |
| 25 | late AudioPlayerUtilType currentType; | 27 | late AudioPlayerUtilType currentType; |
| 26 | bool _wasPlaying = false; | 28 | bool _wasPlaying = false; |
| 29 | + static const TAG = "AudioPlayerUtil"; | ||
| 27 | 30 | ||
| 28 | // 私有构造函数 | 31 | // 私有构造函数 |
| 29 | AudioPlayerUtil._internal() { | 32 | AudioPlayerUtil._internal() { |
| @@ -58,6 +61,7 @@ class AudioPlayerUtil extends WidgetsBindingObserver { | @@ -58,6 +61,7 @@ class AudioPlayerUtil extends WidgetsBindingObserver { | ||
| 58 | 61 | ||
| 59 | // 播放音频 | 62 | // 播放音频 |
| 60 | Future<void> playAudio(AudioPlayerUtilType type) async { | 63 | Future<void> playAudio(AudioPlayerUtilType type) async { |
| 64 | + Log.d("$TAG playAudio $type"); | ||
| 61 | currentType = type; | 65 | currentType = type; |
| 62 | String path = type.path; | 66 | String path = type.path; |
| 63 | await _audioPlayer.play(AssetSource(path.assetMp3), volume: 0.5); | 67 | await _audioPlayer.play(AssetSource(path.assetMp3), volume: 0.5); |
| @@ -66,11 +70,13 @@ class AudioPlayerUtil extends WidgetsBindingObserver { | @@ -66,11 +70,13 @@ class AudioPlayerUtil extends WidgetsBindingObserver { | ||
| 66 | 70 | ||
| 67 | // stop | 71 | // stop |
| 68 | Future<void> stop() async { | 72 | Future<void> stop() async { |
| 73 | + Log.d("$TAG stop _audioPlayer.state=${_audioPlayer.state}"); | ||
| 69 | await _audioPlayer.stop(); | 74 | await _audioPlayer.stop(); |
| 70 | } | 75 | } |
| 71 | 76 | ||
| 72 | // pause | 77 | // pause |
| 73 | Future<void> pause() async { | 78 | Future<void> pause() async { |
| 79 | + Log.d("$TAG pause _audioPlayer.state=${_audioPlayer.state}"); | ||
| 74 | if (_audioPlayer.state == PlayerState.playing) { | 80 | if (_audioPlayer.state == PlayerState.playing) { |
| 75 | await _audioPlayer.pause(); | 81 | await _audioPlayer.pause(); |
| 76 | } | 82 | } |
| @@ -78,6 +84,7 @@ class AudioPlayerUtil extends WidgetsBindingObserver { | @@ -78,6 +84,7 @@ class AudioPlayerUtil extends WidgetsBindingObserver { | ||
| 78 | 84 | ||
| 79 | // resume | 85 | // resume |
| 80 | Future<void> resume() async { | 86 | Future<void> resume() async { |
| 87 | + Log.d("$TAG resume _audioPlayer.state=${_audioPlayer.state}"); | ||
| 81 | if (_audioPlayer.state == PlayerState.paused) { | 88 | if (_audioPlayer.state == PlayerState.paused) { |
| 82 | await _audioPlayer.resume(); | 89 | await _audioPlayer.resume(); |
| 83 | } | 90 | } |
| @@ -85,6 +92,7 @@ class AudioPlayerUtil extends WidgetsBindingObserver { | @@ -85,6 +92,7 @@ class AudioPlayerUtil extends WidgetsBindingObserver { | ||
| 85 | 92 | ||
| 86 | @override | 93 | @override |
| 87 | void didChangeAppLifecycleState(AppLifecycleState state) async { | 94 | void didChangeAppLifecycleState(AppLifecycleState state) async { |
| 95 | + Log.d("$TAG didChangeAppLifecycleState appState=$state _wasPlaying=$_wasPlaying _audioPlayer.state=${_audioPlayer.state}"); | ||
| 88 | if (state == AppLifecycleState.paused) { | 96 | if (state == AppLifecycleState.paused) { |
| 89 | if (_audioPlayer.state == PlayerState.playing) { | 97 | if (_audioPlayer.state == PlayerState.playing) { |
| 90 | _wasPlaying = true; | 98 | _wasPlaying = true; |
| @@ -99,6 +107,7 @@ class AudioPlayerUtil extends WidgetsBindingObserver { | @@ -99,6 +107,7 @@ class AudioPlayerUtil extends WidgetsBindingObserver { | ||
| 99 | } | 107 | } |
| 100 | 108 | ||
| 101 | void dispose() { | 109 | void dispose() { |
| 110 | + Log.d("$TAG dispose _audioPlayer.state=${_audioPlayer.state}"); | ||
| 102 | _audioPlayer.dispose(); | 111 | _audioPlayer.dispose(); |
| 103 | WidgetsBinding.instance.removeObserver(this); | 112 | WidgetsBinding.instance.removeObserver(this); |
| 104 | } | 113 | } |