Skip to content

Instantly share code, notes, and snippets.

@zion830
Created January 2, 2020 18:43
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zion830/d045325ec84b7cb1a545f31f65ff966c to your computer and use it in GitHub Desktop.
Save zion830/d045325ec84b7cb1a545f31f65ff966c to your computer and use it in GitHub Desktop.
[Android] TTS Player 예제
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_play"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="PLAY" />
<Button
android:id="@+id/btn_pause"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="WAIT" />
<Button
android:id="@+id/btn_stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="STOP" />
</LinearLayout>
<EditText
android:id="@+id/et_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="안녕하세요!! 만나서 반갑습니다!"
android:hint="재생할 텍스트 입력"
android:maxLines="3" />
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:scrollbars="vertical"
android:text="입력한 텍스트가 출력되는 영역입니다."
android:textColor="@android:color/black"
android:textSize="16sp" />
</LinearLayout>
package com.example.ttsplayer;
import android.graphics.Color;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.BackgroundColorSpan;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Locale;
public class MainActivity extends AppCompatActivity implements TextPlayer, View.OnClickListener {
private final Bundle params = new Bundle();
private final BackgroundColorSpan colorSpan = new BackgroundColorSpan(Color.YELLOW);
private TextToSpeech tts;
private Button playBtn;
private Button pauseBtn;
private Button stopBtn;
private EditText inputEditText;
private TextView contentTextView;
private PlayState playState = PlayState.STOP;
private Spannable spannable;
private int standbyIndex = 0;
private int lastPlayIndex = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initTTS();
initView();
}
private void initView() {
playBtn = findViewById(R.id.btn_play);
pauseBtn = findViewById(R.id.btn_pause);
stopBtn = findViewById(R.id.btn_stop);
inputEditText = findViewById(R.id.et_input);
contentTextView = findViewById(R.id.tv_content);
playBtn.setOnClickListener(this);
pauseBtn.setOnClickListener(this);
stopBtn.setOnClickListener(this);
}
private void initTTS() {
params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, null);
tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int state) {
if (state == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.KOREAN);
} else {
showState("TTS 객체 초기화 중 문제가 발생했습니다.");
}
}
});
tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String s) {
}
@Override
public void onDone(String s) {
clearAll();
}
@Override
public void onError(String s) {
showState("재생 중 에러가 발생했습니다.");
}
@Override
public void onRangeStart(String utteranceId, int start, int end, int frame) {
changeHighlight(standbyIndex + start, standbyIndex + end);
lastPlayIndex = start;
}
});
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_play:
startPlay();
break;
case R.id.btn_pause:
pausePlay();
break;
case R.id.btn_stop:
stopPlay();
break;
}
showState(playState.getState());
}
@Override
public void startPlay() {
String content = inputEditText.getText().toString();
if (playState.isStopping() && !tts.isSpeaking()) {
setContentFromEditText(content);
startSpeak(content);
} else if (playState.isWaiting()) {
standbyIndex += lastPlayIndex;
startSpeak(content.substring(standbyIndex));
}
playState = PlayState.PLAY;
}
@Override
public void pausePlay() {
if (playState.isPlaying()) {
playState = PlayState.WAIT;
tts.stop();
}
}
@Override
public void stopPlay() {
tts.stop();
clearAll();
}
private void changeHighlight(final int start, final int end) {
runOnUiThread(new Runnable() {
@Override
public void run() {
spannable.setSpan(colorSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
});
}
private void setContentFromEditText(String content) {
contentTextView.setText(content, TextView.BufferType.SPANNABLE);
spannable = (SpannableString) contentTextView.getText();
}
private void startSpeak(final String text) {
tts.speak(text, TextToSpeech.QUEUE_ADD, params, text);
}
private void clearAll() {
playState = PlayState.STOP;
standbyIndex = 0;
lastPlayIndex = 0;
if (spannable != null) {
changeHighlight(0, 0); // remove highlight
}
}
private void showState(final String msg) {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
protected void onPause() {
if (playState.isPlaying()) {
pausePlay();
}
super.onPause();
}
@Override
protected void onResume() {
if (playState.isWaiting()) {
startPlay();
}
super.onResume();
}
@Override
protected void onDestroy() {
tts.stop();
tts.shutdown();
super.onDestroy();
}
}
package com.example.ttsplayer;
public enum PlayState {
PLAY("재생 중"), WAIT("일시정지"), STOP("멈춤");
private String state;
PlayState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public boolean isStopping() {
return this == STOP;
}
public boolean isWaiting() {
return this == WAIT;
}
public boolean isPlaying() {
return this == PLAY;
}
}
package com.example.ttsplayer;
public interface TextPlayer {
void startPlay();
void pausePlay();
void stopPlay();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment