eSpeak NG is an open source speech synthesizer that supports more than hundred languages and accents.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

eSpeakActivity.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /*
  2. * Copyright (C) 2012-2013 Reece H. Dunn
  3. * Copyright (C) 2009 The Android Open Source Project
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package com.reecedunn.espeak;
  18. import android.app.Activity;
  19. import android.content.BroadcastReceiver;
  20. import android.content.Context;
  21. import android.content.Intent;
  22. import android.content.IntentFilter;
  23. import android.os.Build;
  24. import android.os.Bundle;
  25. import android.os.Handler;
  26. import android.os.Message;
  27. import android.preference.PreferenceActivity;
  28. import android.speech.tts.TextToSpeech;
  29. import android.util.Log;
  30. import android.util.Pair;
  31. import android.view.Menu;
  32. import android.view.MenuInflater;
  33. import android.view.MenuItem;
  34. import android.view.View;
  35. import android.widget.ListView;
  36. import android.widget.EditText;
  37. import java.lang.ref.WeakReference;
  38. import java.util.ArrayList;
  39. import java.util.List;
  40. import java.util.Locale;
  41. public class eSpeakActivity extends Activity {
  42. private static final String ACTION_TTS_SETTINGS = "com.android.settings.TTS_SETTINGS";
  43. /** Handler code for TTS initialization hand-off. */
  44. private static final int TTS_INITIALIZED = 1;
  45. private static final int REQUEST_CHECK = 1;
  46. private static final int REQUEST_DEFAULT = 3;
  47. private static final String TAG = "eSpeakActivity";
  48. private enum State {
  49. LOADING,
  50. DOWNLOAD_FAILED,
  51. ERROR,
  52. SUCCESS
  53. }
  54. private State mState;
  55. private TextToSpeech mTts;
  56. private List<Pair<String,String>> mInformation;
  57. private InformationListAdapter mInformationView;
  58. private EditText mText;
  59. private final BroadcastReceiver mOnEspeakInitialized = new BroadcastReceiver() {
  60. @Override
  61. public void onReceive(Context context, Intent intent) {
  62. populateInformationView();
  63. }
  64. };
  65. @Override
  66. public void onCreate(Bundle savedInstanceState) {
  67. super.onCreate(savedInstanceState);
  68. setContentView(R.layout.main);
  69. mInformation = new ArrayList<Pair<String,String>>();
  70. mInformationView = new InformationListAdapter(this, mInformation);
  71. ((ListView)findViewById(R.id.properties)).setAdapter(mInformationView);
  72. mText = (EditText)findViewById(R.id.editText1);
  73. setState(State.LOADING);
  74. checkVoiceData();
  75. findViewById(R.id.speak).setOnClickListener(new View.OnClickListener() {
  76. @Override
  77. @SuppressWarnings("deprecation")
  78. public void onClick(View v) {
  79. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  80. mTts.speak(mText.getText().toString(), TextToSpeech.QUEUE_ADD, null, null);
  81. } else {
  82. mTts.speak(mText.getText().toString(), TextToSpeech.QUEUE_ADD, null);
  83. }
  84. }
  85. });
  86. findViewById(R.id.ssml).setOnClickListener(new View.OnClickListener() {
  87. @Override
  88. public void onClick(View v) {
  89. String ssml =
  90. "<?xml version=\"1.0\"?>\n" +
  91. "<speak xmlns=\"http://www.w3.org/2001/10/synthesis\" version=\"1.0\">\n" +
  92. "\n" +
  93. "</speak>";
  94. mText.setText(ssml);
  95. }
  96. });
  97. }
  98. @Override
  99. public void onStart() {
  100. super.onStart();
  101. final IntentFilter filter = new IntentFilter(TtsService.ESPEAK_INITIALIZED);
  102. registerReceiver(mOnEspeakInitialized, filter);
  103. }
  104. @Override
  105. public void onStop() {
  106. super.onStop();
  107. unregisterReceiver(mOnEspeakInitialized);
  108. if (mTts != null) {
  109. mTts.shutdown();
  110. }
  111. }
  112. @Override
  113. public boolean onCreateOptionsMenu(Menu menu)
  114. {
  115. MenuInflater inflater = getMenuInflater();
  116. inflater.inflate(R.menu.options, menu);
  117. if (Build.VERSION.SDK_INT < 14) {
  118. // Hide the eSpeak setting menu item on pre-ICS.
  119. menu.findItem(R.id.espeakSettings).setVisible(false);
  120. }
  121. return true;
  122. }
  123. @Override
  124. public boolean onOptionsItemSelected(MenuItem item)
  125. {
  126. switch (item.getItemId())
  127. {
  128. case R.id.espeakSettings:
  129. startActivityForResult(new Intent(eSpeakActivity.this, TtsSettingsActivity.class), REQUEST_DEFAULT);
  130. return true;
  131. case R.id.ttsSettings:
  132. launchGeneralTtsSettings();
  133. return true;
  134. }
  135. return super.onOptionsItemSelected(item);
  136. }
  137. /**
  138. * Sets the UI state.
  139. *
  140. * @param state The current state.
  141. */
  142. private void setState(State state) {
  143. mState = state;
  144. switch (mState)
  145. {
  146. case LOADING:
  147. findViewById(R.id.loading).setVisibility(View.VISIBLE);
  148. findViewById(R.id.success).setVisibility(View.GONE);
  149. break;
  150. default:
  151. findViewById(R.id.loading).setVisibility(View.GONE);
  152. findViewById(R.id.success).setVisibility(View.VISIBLE);
  153. break;
  154. }
  155. }
  156. /**
  157. * Launcher the voice data verifier.
  158. */
  159. private void checkVoiceData() {
  160. final Intent checkIntent = new Intent(this, CheckVoiceData.class);
  161. startActivityForResult(checkIntent, REQUEST_CHECK);
  162. }
  163. /**
  164. * Initializes the TTS engine.
  165. */
  166. private void initializeEngine() {
  167. mTts = new TextToSpeech(this, mInitListener);
  168. }
  169. @SuppressWarnings("deprecation")
  170. private Locale getTtsLanguage() {
  171. if (mTts != null) {
  172. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  173. android.speech.tts.Voice voice = mTts.getVoice();
  174. if (voice != null) {
  175. return voice.getLocale();
  176. }
  177. } else {
  178. return mTts.getLanguage();
  179. }
  180. }
  181. return null;
  182. }
  183. private void populateInformationView() {
  184. mInformation.clear();
  185. Locale language = getTtsLanguage();
  186. if (language != null) {
  187. final String currentLocale = getString(R.string.current_tts_locale);
  188. mInformation.add(new Pair<String, String>(currentLocale, language.getDisplayName()));
  189. }
  190. final String availableVoices = getString(R.string.available_voices);
  191. mInformation.add(new Pair<String,String>(availableVoices, Integer.toString(SpeechSynthesis.getVoiceCount())));
  192. final String version = getString(R.string.tts_version);
  193. mInformation.add(new Pair<String,String>(version, SpeechSynthesis.getVersion()));
  194. final String statusText;
  195. switch (mState) {
  196. case ERROR:
  197. statusText = getString(R.string.error_message);
  198. break;
  199. case DOWNLOAD_FAILED:
  200. statusText = getString(R.string.voice_data_failed_message);
  201. break;
  202. default:
  203. if (!getPackageName().equals(mTts.getDefaultEngine())) {
  204. statusText = getString(R.string.set_default_message);
  205. } else {
  206. statusText = null;
  207. }
  208. break;
  209. }
  210. if (statusText != null) {
  211. final String statusLabel = getString(R.string.status);
  212. mInformation.add(new Pair<String,String>(statusLabel, statusText));
  213. }
  214. mInformationView.notifyDataSetChanged();
  215. }
  216. /**
  217. * Handles the result of voice data verification. If verification fails
  218. * following a successful installation, displays an error dialog. Otherwise,
  219. * either launches the installer or attempts to initialize the TTS engine.
  220. *
  221. * @param resultCode The result of voice data verification.
  222. * @param data The intent containing available voices.
  223. */
  224. private void onDataChecked(int resultCode, Intent data) {
  225. if (resultCode != TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
  226. Log.e(TAG, "Voice data check failed (error code: " + resultCode + ").");
  227. setState(State.ERROR);
  228. }
  229. initializeEngine();
  230. }
  231. /**
  232. * Handles the result of TTS engine initialization. Either displays an error
  233. * dialog or populates the activity's UI.
  234. *
  235. * @param status The TTS engine initialization status.
  236. */
  237. private void onInitialized(int status) {
  238. if (status != TextToSpeech.SUCCESS) {
  239. Log.e(TAG, "Initialization failed (status: " + status + ").");
  240. setState(State.ERROR);
  241. } else {
  242. setState(State.SUCCESS);
  243. }
  244. populateInformationView();
  245. }
  246. @Override
  247. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  248. switch (requestCode) {
  249. case REQUEST_CHECK:
  250. onDataChecked(resultCode, data);
  251. break;
  252. case REQUEST_DEFAULT:
  253. initializeEngine();
  254. break;
  255. }
  256. super.onActivityResult(requestCode, resultCode, data);
  257. }
  258. private final TextToSpeech.OnInitListener mInitListener = new TextToSpeech.OnInitListener() {
  259. @Override
  260. public void onInit(int status) {
  261. mHandler.obtainMessage(TTS_INITIALIZED, status, 0).sendToTarget();
  262. }
  263. };
  264. private static class EspeakHandler extends Handler {
  265. private WeakReference<eSpeakActivity> mActivity;
  266. public EspeakHandler(eSpeakActivity activity)
  267. {
  268. mActivity = new WeakReference<eSpeakActivity>(activity);
  269. }
  270. @Override
  271. public void handleMessage(Message msg) {
  272. switch (msg.what) {
  273. case TTS_INITIALIZED:
  274. mActivity.get().onInitialized(msg.arg1);
  275. break;
  276. }
  277. }
  278. }
  279. private final Handler mHandler = new EspeakHandler(this);
  280. private void launchGeneralTtsSettings()
  281. {
  282. Intent intent;
  283. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH)
  284. {
  285. // The Text-to-Speech settings is a Fragment on 3.x:
  286. intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
  287. intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, "com.android.settings.TextToSpeechSettings");
  288. intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, intent.getExtras());
  289. }
  290. else
  291. {
  292. // The Text-to-Speech settings is an Activity on 2.x and 4.x:
  293. intent = new Intent(ACTION_TTS_SETTINGS);
  294. }
  295. startActivityForResult(intent, REQUEST_DEFAULT);
  296. }
  297. }