Commit 2d1ead5369e419d9e972ead8b9373a0ba058d276

Authored by 吴启风
1 parent 9e29ffea

feat:背景音播放优化

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&lt;SectionEvent, SectionState&gt; { @@ -64,15 +64,10 @@ class SectionBloc extends Bloc&lt;SectionEvent, SectionState&gt; {
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&lt;UnitEvent, UnitState&gt; { @@ -48,9 +48,10 @@ class UnitBloc extends Bloc&lt;UnitEvent, UnitState&gt; {
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&lt;ReBackPage&gt; { @@ -26,73 +26,87 @@ class ReBackPageState extends State&lt;ReBackPage&gt; {
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 &#39;package:audioplayers/audioplayers.dart&#39;; @@ -2,6 +2,8 @@ import &#39;package:audioplayers/audioplayers.dart&#39;;
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 }