9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
1
2
3
4
|
import 'dart:io';
import 'dart:async';
import 'package:audio_session/audio_session.dart';
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
5
|
import 'package:flutter/cupertino.dart';
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
6
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
7
8
9
|
import 'package:flutter_sound/flutter_sound.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
10
|
import 'package:wow_english/common/request/dao/listen_dao.dart';
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
11
12
|
import 'package:wow_english/route/route.dart';
import '../../../common/dialogs/show_dialog.dart';
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
13
|
import '../../../common/request/exception.dart';
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
14
|
import '../../../common/speech/chivox_evaluation_channel.dart';
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
15
16
17
18
|
import '../../../models/read_content_entity.dart';
import '../../../utils/loading.dart';
import '../../../utils/toast_util.dart';
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
19
20
21
22
23
24
|
part 'repeat_after_content_event.dart';
part 'repeat_after_content_state.dart';
enum VoiceRecordState {
///未知
voiceRecordUnkonw,
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
25
|
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
26
27
|
///开始录音
voiceRecordStat,
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
28
|
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
29
30
|
///正在录音
voiceRecording,
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
31
|
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
32
33
34
35
|
///录音结束
voiceRecordEnd
}
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
36
|
///驰声测评状态
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
37
|
enum XSVoiceCheckState {
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
38
39
|
///未知
unKnow,
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
40
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
41
42
|
///测评开始
start,
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
43
|
|
31d42f06
liangchengyou
feat:视频跟读录音修改
|
44
45
|
///评测结果
result,
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
46
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
47
48
|
///测评结束
stop,
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
49
50
|
}
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
51
52
|
class RepeatAfterContentBloc
extends Bloc<RepeatAfterContentEvent, RepeatAfterContentState> {
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
53
54
|
final String courseLessonId;
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
55
|
/// 是否正在播放视频
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
56
|
bool _videoPlaying = true;
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
57
|
bool get videoPlaying => _videoPlaying;
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
58
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
59
|
/// 是否正在录音
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
60
|
bool _isRecord = false;
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
61
|
bool get isRecord => _isRecord;
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
62
63
|
/// 驰声评测状态
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
64
65
|
XSVoiceCheckState _xSCheckState = XSVoiceCheckState.unKnow;
XSVoiceCheckState get xSCheckState => _xSCheckState;
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
66
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
67
|
/// 评测结果
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
68
|
Map? _voiceTestResult;
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
69
|
Map? get voiceTestResult => _voiceTestResult;
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
70
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
71
|
/// 录音的次数
|
cc3b183a
liangchengyou
feat:ios启动图/logo
|
72
|
int _recordNumber = 0;
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
73
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
74
75
76
|
/// 录音文件地址
String _path = '';
String get path => _path;
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
77
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
78
79
80
81
82
|
/// 当前播放的视频位置
int _currentPlayIndex = 0;
int get currentPlayIndex => _currentPlayIndex;
/// 录音状态
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
83
|
VoiceRecordState _voiceRecordState = VoiceRecordState.voiceRecordUnkonw;
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
84
85
|
VoiceRecordState get voiceRecordState => _voiceRecordState;
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
86
|
/// 跟读内容数字
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
87
|
List<ReadContentEntity?>? _entityList;
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
88
|
List<ReadContentEntity?>? get entityList => _entityList;
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
89
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
90
|
/// 方法
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
91
|
final ChivoxEvaluationChannel methodChannel = ChivoxEvaluationChannel();
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
92
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
93
94
95
|
///录音
late FlutterSoundRecorder _soundRecorder;
late FlutterSoundPlayer _soundPlayer;
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
96
|
// StreamSubscription? _soundPlayerListen;
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
97
|
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
98
99
|
RepeatAfterContentBloc(this.courseLessonId)
: super(RepeatAfterContentInitial()) {
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
100
|
on<VoiceRecordStateChangeEvent>(_voiceRecordStateChange);
|
cc3b183a
liangchengyou
feat:ios启动图/logo
|
101
|
on<PostFollowReadContentEvent>(_postFollowReadContent);
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
102
|
on<ChangeVideoPlayIndexEvent>(_changeVideoPlayIndex);
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
103
104
|
on<VideoPlayChangeEvent>(_videoPlayStateChange);
on<RecordeVoicePlayEvent>(_recordeVoicePlay);
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
105
106
|
on<StarRecordVoiceEvent>(_starRecordVoice);
on<StopRecordVoiceEvent>(_stopRecordVoice);
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
107
|
on<XSVoiceResultEvent>(_voiceXsResult);
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
108
109
110
111
|
on<RequestDataEvent>(_requestData);
on<XSVoiceTestEvent>(_voiceXsTest);
on<XSVoiceStopEvent>(_voiceXsStop);
on<VoiceRecordEvent>(_voiceRecord);
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
112
113
|
on<InitBlocEvent>(_initBlocData);
}
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
114
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
115
|
@override
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
116
117
118
119
|
Future<void> close() async {
await _releaseFlauto();
await _voiceXsCancel();
await methodChannel.dispose();
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
120
121
|
return super.close();
}
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
122
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
123
|
///初始化功能
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
124
125
|
void _initBlocData(
InitBlocEvent event, Emitter<RepeatAfterContentState> emitter) async {
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
126
|
methodChannel.setMethodCallHandler((call) async {
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
127
128
|
if (call.method == 'voiceResult') {
//评测结果
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
129
130
|
add(XSVoiceResultEvent(call.arguments));
add(PostFollowReadContentEvent());
|
31d42f06
liangchengyou
feat:视频跟读录音修改
|
131
132
133
134
135
|
return;
}
if (call.method == 'voiceEnd') {
return;
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
136
|
}
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
137
138
139
140
141
142
|
if (call.method == 'voiceFail') {
_xSCheckState = XSVoiceCheckState.unKnow;
add(VoiceRecordStateChangeEvent(_voiceRecordState));
showToast('评测失败');
}
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
143
|
});
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
144
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
145
146
|
//录音
_soundRecorder = FlutterSoundRecorder();
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
147
148
|
//音屏
_soundPlayer = FlutterSoundPlayer();
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
149
150
|
await _init();
await methodChannel.invokeMethod('initVoiceSdk', {});
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
151
152
|
}
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
153
|
Future<void> _init() async {
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
154
|
await _soundRecorder.openRecorder();
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
155
156
|
await _soundRecorder
.setSubscriptionDuration(const Duration(milliseconds: 10));
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
157
158
159
160
161
|
//设置音频
final session = await AudioSession.instance;
await session.configure(AudioSessionConfiguration(
avAudioSessionCategory: AVAudioSessionCategory.playAndRecord,
avAudioSessionCategoryOptions:
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
162
163
|
AVAudioSessionCategoryOptions.allowBluetooth |
AVAudioSessionCategoryOptions.defaultToSpeaker,
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
164
165
|
avAudioSessionMode: AVAudioSessionMode.spokenAudio,
avAudioSessionRouteSharingPolicy:
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
166
|
AVAudioSessionRouteSharingPolicy.defaultPolicy,
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
167
168
169
170
171
172
173
174
175
176
177
|
avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none,
androidAudioAttributes: const AndroidAudioAttributes(
contentType: AndroidAudioContentType.speech,
flags: AndroidAudioFlags.none,
usage: AndroidAudioUsage.voiceCommunication,
),
androidAudioFocusGainType: AndroidAudioFocusGainType.gain,
androidWillPauseWhenDucked: true,
));
await _soundPlayer.closePlayer();
await _soundPlayer.openPlayer();
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
178
179
|
await _soundPlayer
.setSubscriptionDuration(const Duration(milliseconds: 10));
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
180
181
182
|
}
///请求数据
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
183
184
|
void _requestData(
RequestDataEvent event, Emitter<RepeatAfterContentState> emitter) async {
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
185
186
187
188
189
190
191
|
try {
await loading(() async {
_entityList = await ListenDao.readContent(courseLessonId);
emitter(RequestDataState());
});
} catch (e) {
if (e is ApiException) {
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
192
|
showToast(e.message ?? '请求失败,请检查网络连接');
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
193
194
195
196
|
}
}
}
|
68dd7ba8
liangchengyou
feat:首页主题颜色+已知问题修改
|
197
|
///提交跟读结果
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
198
199
|
void _postFollowReadContent(PostFollowReadContentEvent event,
Emitter<RepeatAfterContentState> emitter) async {
|
cc3b183a
liangchengyou
feat:ios启动图/logo
|
200
|
try {
|
68dd7ba8
liangchengyou
feat:首页主题颜色+已知问题修改
|
201
|
ReadContentEntity entity = _entityList![_currentPlayIndex]!;
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
202
|
await ListenDao.followResult(_recordNumber.toString(), entity.id);
|
cc3b183a
liangchengyou
feat:ios启动图/logo
|
203
|
} catch (e) {
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
204
|
if (e is ApiException) {}
|
cc3b183a
liangchengyou
feat:ios启动图/logo
|
205
206
207
|
}
}
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
208
209
|
void _videoPlayStateChange(VideoPlayChangeEvent event,
Emitter<RepeatAfterContentState> emitter) async {
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
210
211
212
213
|
_videoPlaying = !_videoPlaying;
emitter(VideoPlayChangeState());
}
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
214
215
|
void _voiceRecord(
VoiceRecordEvent event, Emitter<RepeatAfterContentState> emitter) async {
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
216
217
218
219
|
_isRecord = !_isRecord;
emitter(VoiceRecordChangeState());
}
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
220
221
|
void _voiceRecordStateChange(VoiceRecordStateChangeEvent event,
Emitter<RepeatAfterContentState> emitter) async {
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
222
223
224
225
|
_voiceRecordState = event.voiceRecordState;
emitter(VoiceRecordStateChange());
}
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
226
227
228
|
///驰声测试
void _voiceXsTest(
XSVoiceTestEvent event, Emitter<RepeatAfterContentState> emitter) async {
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
229
230
231
|
_recordNumber += 1;
_xSCheckState = XSVoiceCheckState.start;
emitter(XSVoiceTestState());
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
232
233
234
235
236
237
|
await methodChannel.invokeMethod('startLocalVoice', {
'type': event.type,
'word': event.testWord,
'voicePath': _path,
'userId': event.userId.toString()
});
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
238
239
240
|
}
///终止评测
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
241
242
243
|
void _voiceXsStop(
XSVoiceStopEvent event, Emitter<RepeatAfterContentState> emitter) async {
await methodChannel.invokeMethod('stopVoice');
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
244
245
|
}
|
6b0947ca
吴启风
feat:绘本增加initVoic...
|
246
|
///取消评测(用于处理退出页面后录音未停止等异常情况的保护操作)
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
247
248
|
Future<void> _voiceXsCancel() async {
await methodChannel.invokeMethod('cancelVoice');
|
6b0947ca
吴启风
feat:绘本增加initVoic...
|
249
250
|
}
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
251
252
253
|
///驰声评测结果
void _voiceXsResult(XSVoiceResultEvent event,
Emitter<RepeatAfterContentState> emitter) async {
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
254
255
|
final Map args = event.message as Map;
final result = args['result'] as Map;
|
37b78a15
liangchengyou
feat:添加录音插件
|
256
|
final overall = result['overall'].toString();
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
257
|
_voiceTestResult = {'overall': overall};
|
31d42f06
liangchengyou
feat:视频跟读录音修改
|
258
|
_xSCheckState = XSVoiceCheckState.result;
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
259
260
261
262
|
emitter(XSVoiceTestState());
}
///播放声音
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
263
264
|
void _recordeVoicePlay(RecordeVoicePlayEvent event,
Emitter<RepeatAfterContentState> emitter) async {
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
265
266
267
268
|
if (await _fileExists(_path)) {
if (_soundPlayer.isPlaying) {
_soundPlayer.stopPlayer();
}
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
269
|
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
270
|
await _soundPlayer.startPlayer(
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
271
|
fromURI: path, codec: Codec.pcm16WAV, whenFinished: () {});
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
272
273
|
}
}
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
274
275
|
///更改播放的视频
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
276
277
|
void _changeVideoPlayIndex(ChangeVideoPlayIndexEvent event,
Emitter<RepeatAfterContentState> emitter) async {
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
278
279
280
281
|
if (_entityList == null || _entityList!.isEmpty) {
return;
}
if (event.isNext) {
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
282
|
if (_currentPlayIndex < _entityList!.length - 1) {
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
283
284
285
|
_currentPlayIndex++;
}
} else {
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
286
|
if (_currentPlayIndex > 0) {
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
287
288
289
|
_currentPlayIndex--;
}
}
|
7d6a6ddc
liangchengyou
feat:1.0.1优化
|
290
291
|
emitter(ChangeVideoPlayIndexState(event.isNext));
}
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
292
293
|
///开始录音
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
294
295
|
void _starRecordVoice(StarRecordVoiceEvent event,
Emitter<RepeatAfterContentState> emitter) async {
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
296
297
298
299
300
301
302
303
|
try {
await getPermissionStatus().then((value) async {
if (!value) {
debugPrint('失败$value');
return;
}
Directory tempDir = await getTemporaryDirectory();
var time = DateTime.now().millisecondsSinceEpoch;
|
31d42f06
liangchengyou
feat:视频跟读录音修改
|
304
|
String path = '${tempDir.path}/$time${ext[Codec.pcm16WAV.index]}';
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
305
306
307
308
309
|
_path = path;
debugPrint('=====> 准备开始录音');
await _soundRecorder.startRecorder(
toFile: path,
|
31d42f06
liangchengyou
feat:视频跟读录音修改
|
310
|
codec: Codec.pcm16WAV,
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
311
312
313
|
);
debugPrint('=====> 开始录音');
_voiceRecordState = VoiceRecordState.voiceRecording;
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
314
|
_xSCheckState = XSVoiceCheckState.unKnow;
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
315
316
317
318
319
320
321
322
|
emitter(VoiceRecordStateChange());
});
} catch (error) {
await _soundRecorder.stopRecorder();
}
}
///停止录音
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
323
324
|
void _stopRecordVoice(StopRecordVoiceEvent event,
Emitter<RepeatAfterContentState> emitter) async {
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
|
debugPrint('=====> 停止录音');
await _soundRecorder.stopRecorder();
_voiceRecordState = VoiceRecordState.voiceRecordEnd;
emitter(VoiceRecordStateChange());
}
/// 判断文件是否存在
Future<bool> _fileExists(String path) async {
return await File(path).exists();
}
///获取权限
Future<bool> getPermissionStatus() async {
Permission permission = Permission.microphone;
PermissionStatus status = await permission.status;
if (status.isGranted) {
return true;
} else if (status.isDenied) {
requestPermission(permission);
} else if (status.isPermanentlyDenied) {
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
345
|
showDialog();
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
346
347
|
} else if (status.isRestricted) {
requestPermission(permission);
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
348
|
} else {}
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
349
350
351
352
353
354
355
356
357
358
359
360
|
return false;
}
/// 释放录音
Future<void> _releaseFlauto() async {
await _soundRecorder.closeRecorder();
}
///申请权限
void requestPermission(Permission permission) async {
PermissionStatus status = await permission.request();
if (status.isPermanentlyDenied) {
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
361
|
showDialog();
|
9efff6ae
liangchengyou
feat:视频跟读逻辑修改
|
362
363
|
}
}
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
364
365
|
void showDialog() async {
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
366
|
showTwoActionDialog('提示', '取消', '去设置', '请进入设置页打开麦克风权限', leftTap: () {
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
367
|
popPage();
|
0fa4e405
吴启风
feat: 将语音评测从先声迁移至驰声
|
368
|
}, rightTap: () {
|
934e2b47
liangchengyou
feat:权限调整+课程进度接口对接
|
369
370
371
372
|
popPage();
openAppSettings();
});
}
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
373
|
}
|