안드로이드의 경우 minSDK가 존재
minSdkVersion 21
또한 Native레벨에서 안드로이드는 Pause 기능이 없기 때문에, 임시방편으로 pause를 구현해놓은 상태. 때문에 안드로이드에서 pause 기능을 사용하려면 SDK 26 이상이어야 한다
onRangeStart()
method to determine the index of start when pause
is invoked. We use that index to create a new text the next time speak
is invoked. Due to using onRangeStart()
, pause works on SDK versions >= 26. Also, if using start
and end
offsets inside of setProgressHandler()
, you'll need to keep a track of them if using pause
since they will update once the new text is created when speak
is called after being paused.tts_handler
이용시 riverpod으로 관리하는 TTSstate
를 관리해주기 위해 WidgetRef
를 파라미터로 받도록 생성TTSUtil(ref).init();
...
class TTSUtil {
TTSUtil._internal();
factory TTSUtil(WidgetRef ref) {
_instance.ref = ref;
return _instance;
}
final FlutterTts ttsUtil = FlutterTts();
static final TTSUtil _instance = TTSUtil._internal();
late WidgetRef ref;
// init 시 세팅해줘야하는 기본 파라미터들
Future<void> init() async {
await _setAwaitOptions();
await ttsUtil.setLanguage('ko-KR');
await ttsUtil.setVolume(volume);
await ttsUtil.setSpeechRate(rate);
await ttsUtil.setPitch(pitch);
}
Future _setAwaitOptions() async {
await ttsUtil.awaitSpeakCompletion(true);
}
...
enum TTSState { playing, stopped, paused, continued }
(keepAlive: true)
class TTS extends _$TTS {
TTSState build() {
return TTSState.stopped;
}
void setTTSState(TTSState ttsState) {
state = ttsState;
}
}
enum TTSVoice { women1, women2, man1, man2 }
...
Future setVoice({required TTSVoice newVoiceenum}) async {
final String newVoiceName;
switch (newVoiceenum) {
case TTSVoice.women1:
newVoiceName = 'ko-KR-language';
break;
case TTSVoice.women2:
newVoiceName = 'ko-kr-x-kob-local';
break;
case TTSVoice.man1:
newVoiceName = 'ko-kr-x-kod-local';
break;
case TTSVoice.man2:
newVoiceName = 'ko-kr-x-koc-local';
break;
}
await ttsUtil.setVoice({
'name': newVoiceName,
'locale': 'ko-KR',
});
}
void setCompletionHandler({required Function() completionHandler}) {
ttsUtil.setCompletionHandler(() {
ref.read(tTSProvider.notifier).setTTSState(TTSState.stopped);
completionHandler();
});
}
late final TTSUtil ttsUtil;
void initState() {
super.initState();
ttsUtil = TTSUtil(ref);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
ttsUtil.speak(
newVoiceText: '첫번째 나올 TTS 문장'
);
});
}
Widget build(BuildContext context) {
//tts의 index단계가 끝날 때마다 0.5초 대기 시간 가진 후 다음 새로운 텍스트를 speak하는 코드
ttsUtil.setCompletionHandler(completionHandler: () async {
await Future.delayed(const Duration(milliseconds: 500), () async {
await _handleTTSProgress();
});
});
...
// 넘어가기 버튼이 클릭되면 tts stop & handle
CustomTextButton.create(
text: '넘어가기',
onPressed: () async {
await ttsUtil.stop();
await _handleTTSProgress();
},
),
...
Future<void> _handleTTSProgress(
) async {
ttsUtil.speak(
newVoiceText:' ... ',
);
}