2012년 04월 15일
[Android] 한글 TextToSpeech 서비스 사용 예제
안드로이드상 에서 한글 TTS 기능을 사용해 본다. (안드로이드에서는 기본적으로 한글 TTS 기능을 지원하지 않기에 삼성 TTS, 또는 SVOX 를 설치하여야 한다.)
TextToSpeechHandle 클래스- TTS 서비스를 초기화 하고, 관련 함수를 Wrapping 한 클래스
- Messenger 를 이용하여 음성 출력후 완료 응답을 받을수 있도록 구현
1 package net.ecilaz.TestTTS; 2 3 import java.util.HashMap; 4 import java.util.Locale; 5 6 import android.content.Context; 7 import android.media.AudioManager; 8 import android.os.Message; 9 import android.os.Messenger; 10 import android.os.RemoteException; 11 import android.speech.tts.TextToSpeech; 12 import android.speech.tts.TextToSpeech.OnInitListener; 13 import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener; 14 15 public class TextToSpeechHandle implements OnInitListener, OnUtteranceCompletedListener { 16 17 public static final String initialize_ = "initalize"; 18 public static final int SUCCESS = 1; 19 public static final int FAILURE = 0; 20 21 private boolean initialize_ok_ = false; 22 private Context context_ = null; 23 private TextToSpeech text_to_speech_ = null; 24 private HashMap<String, String> hash_alarm_ = null; 25 private HashMap<String, Messenger> hash_cb_ = null; 26 private HashMap<String, Integer> hash_res_ = null; 27 28 --* 29 * 기본 생성자이며 TextToSpeech 기능을 이용하기 위해서는 Initailze 함수를 명시적으로 호출해야 한다. 30 * ex) 31 * TextToSpeechHandler ttsh = new TextToSpeechHandle(); 32 * ttsh.Initailze(); 33 -- 34 public TextToSpeechHandle() { 35 } 36 37 --* 38 * 39 * @param context : 유저의 액티비티 또는 서비스의 인스턴스 40 -- 41 public TextToSpeechHandle(Context context) { 42 Initailize(context, 0, null); 43 } 44 45 --* 46 * 47 * @param context : 유저의 액티티비 또는 서비스의 인스턴스 48 * @param res : TextToSpeech 서버스를 초기화 하고 성공 여부를 알려줄 Message 의 what 값 49 * @param initailize_cb : TextToSpeech 서비스를 초기화 하고 성공여부를 알려줄 콜백용 Messenger 50 -- 51 public TextToSpeechHandle(Context context, int res, Messenger initailize_cb) { 52 Initailize(context, res, initailize_cb); 53 } 54 55 --* 56 * 57 * @param context : 유저의 액티티비 또는 서비스의 인스턴스 58 * @param res : TextToSpeech 서버스를 초기화 하고 성공 여부를 알려줄 Message 의 what 값 59 * @param initailize_cb : TextToSpeech 서비스를 초기화 하고 성공여부를 알려줄 콜백용 Messenger 60 -- 61 public void Initailize(Context context, int res, Messenger initailize_cb) { 62 63 //초기화 후 실수로 재 호출 하지 않도록 막아준다. 64 if(IsAvailableTextToSpeech() == true) { 65 LogUtil.Trace(); 66 return; 67 } 68 69 hash_alarm_ = new HashMap<String, String>(); 70 hash_cb_ = new HashMap<String, Messenger>(); 71 hash_res_ = new HashMap<String, Integer>(); 72 73 if(initailize_cb != null) { 74 hash_cb_.put(initialize_, initailize_cb); 75 hash_res_.put(initialize_, res); 76 } 77 78 this.context_ = context; 79 80 text_to_speech_ = new TextToSpeech(context_, this); 81 text_to_speech_.setOnUtteranceCompletedListener(this); 82 } 83 84 --* 85 * TextToSpeech 서비스를 종료한다. 86 -- 87 public void Finalize() { 88 text_to_speech_.shutdown(); 89 initialize_ok_ = false; 90 } 91 92 --* 93 * 94 * @return : TextToSpeech 서비스의 초기화 성공 여부를 리턴함 (true: 성공, false: 실패) 95 -- 96 public boolean IsAvailableTextToSpeech() { 97 return initialize_ok_; 98 } 99 100 --* 101 * 102 * @param text : TextToSpeech 서비스를 이용하여 음성을 출력할 메시지 103 * @param flush_yn : 음성출력의 큐 모드 (true: 큐를 비우고 바로 출력, false: 메시지를 큐잉) 104 -- 105 public void speakText(String text, boolean flush_yn) { 106 speakText(text, null, 0, null, flush_yn); 107 } 108 109 --* 110 * 111 * @param text : TextToSpeech 서비스를 이용하여 음성을 출력할 메시지 112 * @param request_id : 음성 출력 요청을 구분할 ID(콜백 Messenger 를 구분할 ID 로 사용, null일 경우 콜백 호출 안함) 113 * @param res : text 를 음성 출력한후 완료 콜백 Message 의 what 값 114 * @param speak_cb : text 를 음성 출력한후 완료 콜백용 Messenger(null 일 경우 콜백 호출 안함) 115 * @param flush_yn : 음성출력의 큐 모드 (true: 큐를 비우고 바로 출력, false: 메시지를 큐잉) 116 -- 117 public void speakText(String text, String request_id, int res, Messenger speak_cb, boolean flush_yn) { 118 119 if(speak_cb == null || request_id == "" || request_id == null) { 120 hash_alarm_.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_ALARM)); 121 } 122 else { 123 hash_alarm_.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, request_id); 124 hash_cb_.put(request_id, speak_cb); 125 hash_res_.put(request_id, res); 126 } 127 128 text_to_speech_.speak(text, flush_yn ? TextToSpeech.QUEUE_FLUSH : TextToSpeech.QUEUE_ADD, hash_alarm_); 129 } 130 131 --* 132 * 133 * @param request_id : 음성 출력 요청을 구분할 ID(콜백 Messenger 를 구분할 ID 로 사용) 134 * @param success_yn : 요청 처리 결과 여부 (1: 성공, 0: 실패) 135 -- 136 private void InvokeCallback(String request_id, int success_yn) { 137 Messenger messenger = hash_cb_.get(request_id); 138 if(messenger == null) { return ; } 139 140 Integer res = hash_res_.get(request_id); 141 if(res == null) { return ; } 142 143 try { 144 145 Message msg = Message.obtain(); 146 msg.what = res; 147 msg.arg1 = success_yn; 148 msg.obj = request_id; 149 messenger.send(msg); 150 151 } catch (RemoteException e) { 152 LogUtil.Trace(e); 153 } 154 finally { 155 hash_cb_.remove(request_id); 156 hash_res_.remove(request_id); 157 } 158 } 159 160 --* 161 * TextToSpeech.OnInitListener 구현 : TTS 언어를 Locale.KOREA 로 셋팅하고 언어 지원 여부를 검사한다. 162 * 163 -- 164 public void onInit(int status) { 165 166 if(status != TextToSpeech.SUCCESS) { 167 LogUtil.Debug(String.format("TextToSpeechManager.onInit(%d) fail!", status)); 168 InvokeCallback(initialize_, FAILURE); 169 return ; 170 } 171 172 int result = text_to_speech_.setLanguage(Locale.KOREA); 173 if(result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) { 174 LogUtil.Debug(String.format("TextToSpeech.setLanguage(%d) fail!", Locale.KOREA)); 175 InvokeCallback(initialize_, FAILURE); 176 return ; 177 } 178 179 initialize_ok_ = true; 180 InvokeCallback(initialize_, SUCCESS); 181 } 182 183 --* 184 * TextToSpeech.OnUtteranceCompletedListener 구현 : 음성을 출력이 완료되면 콜백을 호출한다. 185 * 186 -- 187 public void onUtteranceCompleted(String utterance_id) { 188 InvokeCallback(utterance_id, SUCCESS); 189 } 190 } 191TestTTSActivity 클래스
- TextToSpeechHandle 을 생성하고, EditText 의 내용을 음성 출력하는 예제
1 package net.ecilaz.TestTTS; 2 3 import android.app.Activity; 4 import android.content.Intent; 5 import android.os.Bundle; 6 import android.os.Handler; 7 import android.os.Message; 8 import android.os.Messenger; 9 import android.speech.tts.TextToSpeech; 10 import android.view.View; 11 import android.view.View.OnClickListener; 12 import android.widget.Button; 13 import android.widget.EditText; 14 15 public class TestTTSActivity extends Activity { 16 17 private static final int MY_DATA_CHECK_CODE = 0; 18 private static final int RES_TTS_INITIALIZE = 2; 19 20 private EditText edittext_; 21 private Button button_; 22 private TextToSpeechHandle ttsh_; 23 private Messenger messenger_ = new Messenger(new IncomingHandler()); 24 25 class IncomingHandler extends Handler { 26 @Override 27 public void handleMessage(Message msg) { 28 switch (msg.what) { 29 case RES_TTS_INITIALIZE: 30 if(msg.arg1 == 1) { 31 ttsh_.speakText("TTS 서비스가 정상적으로 초기화 되었습니다.", false); 32 button_.setEnabled(true); 33 } 34 break; 35 default: 36 super.handleMessage(msg); 37 break; 38 } 39 } 40 } 41 42 43 --* Called when the activity is first created. -- 44 @Override 45 public void onCreate(Bundle savedInstanceState) { 46 super.onCreate(savedInstanceState); 47 setContentView(R.layout.main); 48 49 50 Intent checkIntent = new Intent(); 51 checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA); 52 startActivityForResult(checkIntent, MY_DATA_CHECK_CODE ); 53 54 edittext_ = (EditText)findViewById(R.id.et); 55 edittext_.setEnabled(true); 56 button_ = (Button)findViewById(R.id.read); 57 button_.setEnabled(false); 58 ttsh_ = new TextToSpeechHandle(); 59 60 button_.setOnClickListener(new OnClickListener() { 61 public void onClick(View v) { 62 String text = edittext_.getText().toString(); 63 ttsh_.speakText(text, true); 64 }}); 65 66 } 67 68 @Override 69 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 70 71 if(requestCode == MY_DATA_CHECK_CODE) { 72 73 if(resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) { 74 ttsh_.Initailize(this, RES_TTS_INITIALIZE, messenger_); 75 } 76 else { 77 Intent installIntent = new Intent(); 78 installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA); 79 startActivity(installIntent); 80 } 81 } 82 } 83 84 @Override 85 public void onPause(){ 86 super.onPause(); 87 } 88 89 @Override 90 public void onResume(){ 91 super.onResume(); 92 } 93 94 @Override 95 public void onDestroy(){ 96 super.onDestroy(); 97 ttsh_.Finalize(); 98 } 99 }LogUtil 클래스
- LogCat 을 이용하여 로그를 남긴다.
1 package net.ecilaz.TestTTS; 2 3 import android.util.Log; 4 5 public class LogUtil { 6 7 private static final String TAG = "TestTTS"; 8 9 public static void Info(String msg) { 10 Log.i(TAG, msg); 11 } 12 13 public static void Debug(String msg) { 14 Log.d(TAG, msg); 15 } 16 17 public static void Warning(String msg) { 18 Log.w(TAG, msg); 19 } 20 21 public static void Error(String msg) { 22 Log.e(TAG, msg); 23 } 24 25 public static void Trace() { 26 java.lang.Exception e = new java.lang.Exception(); 27 StackTraceElement ste[] = e.getStackTrace(); 28 29 Log.e(TAG, "[Trace] " + ste[1].getClassName() + "." 30 + ste[1].getMethodName() + "(" + ste[1].getFileName() + ":" 31 + ste[1].getLineNumber() + ")"); 32 } 33 34 public static void Trace(Exception e) { 35 StackTraceElement array[] = e.getStackTrace(); 36 37 Log.e(TAG, "[StackTrace]"); 38 for(StackTraceElement ste : array) { 39 40 Log.e(TAG, " " + ste.getClassName() + "." 41 + ste.getMethodName() + "(" + ste.getFileName() + ":" 42 + ste.getLineNumber() + ")"); 43 } 44 } 45 }참고
- TTS 초기화가 완료되는 시점을 알수 없기에 TextToSpeech.OnInitListener 인터페이스의 onInit()에서 Messenger 를 이용하여 완료 응답을 받도록 함.
- 또한, 특정 Text 의 음성 출력 완료 응답을 받기 위해 Messenger 를 이용함.
- TestTTSActivity 클래스는 에러 처리가 제대로 되어 있지 않기에 예제로써 만 사용해야 함
# by | 2012/04/15 04:15 | Programming. | 트랙백 | 덧글(0)
























