TextToSpeech.java revision 6a8b73be572f37b471322e7d49b44c3783633d96
1/* 2 * Copyright (C) 2009 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16package android.speech.tts; 17 18import android.speech.tts.ITts; 19import android.speech.tts.ITtsCallback; 20 21import android.annotation.SdkConstant; 22import android.annotation.SdkConstant.SdkConstantType; 23import android.content.ComponentName; 24import android.content.Context; 25import android.content.Intent; 26import android.content.ServiceConnection; 27import android.media.AudioManager; 28import android.os.IBinder; 29import android.os.RemoteException; 30import android.util.Log; 31 32import java.util.HashMap; 33import java.util.Locale; 34 35/** 36 * 37 * Synthesizes speech from text for immediate playback or to create a sound file. 38 * <p>A TextToSpeech instance can only be used to synthesize text once it has completed its 39 * initialization. Implement the {@link TextToSpeech.OnInitListener} to be 40 * notified of the completion of the initialization.<br> 41 * When you are done using the TextToSpeech instance, call the {@link #shutdown()} method 42 * to release the native resources used by the TextToSpeech engine. 43 * 44 */ 45public class TextToSpeech { 46 47 /** 48 * Denotes a successful operation. 49 */ 50 public static final int SUCCESS = 0; 51 /** 52 * Denotes a generic operation failure. 53 */ 54 public static final int ERROR = -1; 55 56 /** 57 * Queue mode where all entries in the playback queue (media to be played 58 * and text to be synthesized) are dropped and replaced by the new entry. 59 */ 60 public static final int QUEUE_FLUSH = 0; 61 /** 62 * Queue mode where the new entry is added at the end of the playback queue. 63 */ 64 public static final int QUEUE_ADD = 1; 65 66 67 /** 68 * Denotes the language is available exactly as specified by the locale. 69 */ 70 public static final int LANG_COUNTRY_VAR_AVAILABLE = 2; 71 72 73 /** 74 * Denotes the language is available for the language and country specified 75 * by the locale, but not the variant. 76 */ 77 public static final int LANG_COUNTRY_AVAILABLE = 1; 78 79 80 /** 81 * Denotes the language is available for the language by the locale, 82 * but not the country and variant. 83 */ 84 public static final int LANG_AVAILABLE = 0; 85 86 /** 87 * Denotes the language data is missing. 88 */ 89 public static final int LANG_MISSING_DATA = -1; 90 91 /** 92 * Denotes the language is not supported. 93 */ 94 public static final int LANG_NOT_SUPPORTED = -2; 95 96 97 /** 98 * Broadcast Action: The TextToSpeech synthesizer has completed processing 99 * of all the text in the speech queue. 100 */ 101 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 102 public static final String ACTION_TTS_QUEUE_PROCESSING_COMPLETED = 103 "android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED"; 104 105 106 /** 107 * Interface definition of a callback to be invoked indicating the completion of the 108 * TextToSpeech engine initialization. 109 */ 110 public interface OnInitListener { 111 /** 112 * Called to signal the completion of the TextToSpeech engine initialization. 113 * @param status {@link TextToSpeech#SUCCESS} or {@link TextToSpeech#ERROR}. 114 */ 115 public void onInit(int status); 116 } 117 118 /** 119 * Interface definition of a callback to be invoked indicating the TextToSpeech engine has 120 * completed synthesizing an utterance with an utterance ID set. 121 * 122 */ 123 public interface OnUtteranceCompletedListener { 124 /** 125 * Called to signal the completion of the synthesis of the utterance that was identified 126 * with the string parameter. This identifier is the one originally passed in the 127 * parameter hashmap of the synthesis request in 128 * {@link TextToSpeech#speak(String, int, HashMap)} or 129 * {@link TextToSpeech#synthesizeToFile(String, HashMap, String)} with the 130 * {@link TextToSpeech.Engine#KEY_PARAM_UTTERANCE_ID} key. 131 * @param utteranceId the identifier of the utterance. 132 */ 133 public void onUtteranceCompleted(String utteranceId); 134 } 135 136 137 /** 138 * Internal constants for the TextToSpeech functionality 139 * 140 */ 141 public class Engine { 142 // default values for a TTS engine when settings are not found in the provider 143 /** 144 * {@hide} 145 */ 146 public static final int DEFAULT_RATE = 100; // 1x 147 /** 148 * {@hide} 149 */ 150 public static final int DEFAULT_PITCH = 100;// 1x 151 /** 152 * {@hide} 153 */ 154 public static final int USE_DEFAULTS = 0; // false 155 /** 156 * {@hide} 157 */ 158 public static final String DEFAULT_SYNTH = "com.svox.pico"; 159 160 // default values for rendering 161 /** 162 * Default audio stream used when playing synthesized speech. 163 */ 164 public static final int DEFAULT_STREAM = AudioManager.STREAM_MUSIC; 165 166 // return codes for a TTS engine's check data activity 167 /** 168 * Indicates success when checking the installation status of the resources used by the 169 * TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. 170 */ 171 public static final int CHECK_VOICE_DATA_PASS = 1; 172 /** 173 * Indicates failure when checking the installation status of the resources used by the 174 * TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. 175 */ 176 public static final int CHECK_VOICE_DATA_FAIL = 0; 177 /** 178 * Indicates erroneous data when checking the installation status of the resources used by 179 * the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. 180 */ 181 public static final int CHECK_VOICE_DATA_BAD_DATA = -1; 182 /** 183 * Indicates missing resources when checking the installation status of the resources used 184 * by the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. 185 */ 186 public static final int CHECK_VOICE_DATA_MISSING_DATA = -2; 187 /** 188 * Indicates missing storage volume when checking the installation status of the resources 189 * used by the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. 190 */ 191 public static final int CHECK_VOICE_DATA_MISSING_VOLUME = -3; 192 193 // intents to ask engine to install data or check its data 194 /** 195 * Activity Action: Triggers the platform TextToSpeech engine to 196 * start the activity that installs the resource files on the device 197 * that are required for TTS to be operational. Since the installation 198 * of the data can be interrupted or declined by the user, the application 199 * shouldn't expect successful installation upon return from that intent, 200 * and if need be, should check installation status with 201 * {@link #ACTION_CHECK_TTS_DATA}. 202 */ 203 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 204 public static final String ACTION_INSTALL_TTS_DATA = 205 "android.speech.tts.engine.INSTALL_TTS_DATA"; 206 207 /** 208 * Broadcast Action: broadcast to signal the completion of the installation of 209 * the data files used by the synthesis engine. Success or failure is indicated in the 210 * {@link #EXTRA_TTS_DATA_INSTALLED} extra. 211 */ 212 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 213 public static final String ACTION_TTS_DATA_INSTALLED = 214 "android.speech.tts.engine.TTS_DATA_INSTALLED"; 215 /** 216 * Activity Action: Starts the activity from the platform TextToSpeech 217 * engine to verify the proper installation and availability of the 218 * resource files on the system. Upon completion, the activity will 219 * return one of the following codes: 220 * {@link #CHECK_VOICE_DATA_PASS}, 221 * {@link #CHECK_VOICE_DATA_FAIL}, 222 * {@link #CHECK_VOICE_DATA_BAD_DATA}, 223 * {@link #CHECK_VOICE_DATA_MISSING_DATA}, or 224 * {@link #CHECK_VOICE_DATA_MISSING_VOLUME}. 225 * <p> Moreover, the data received in the activity result will contain the following 226 * fields: 227 * <ul> 228 * <li>{@link #EXTRA_VOICE_DATA_ROOT_DIRECTORY} which 229 * indicates the path to the location of the resource files,</li> 230 * <li>{@link #EXTRA_VOICE_DATA_FILES} which contains 231 * the list of all the resource files,</li> 232 * <li>and {@link #EXTRA_VOICE_DATA_FILES_INFO} which 233 * contains, for each resource file, the description of the language covered by 234 * the file in the xxx-YYY format, where xxx is the 3-letter ISO language code, 235 * and YYY is the 3-letter ISO country code.</li> 236 * </ul> 237 */ 238 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 239 public static final String ACTION_CHECK_TTS_DATA = 240 "android.speech.tts.engine.CHECK_TTS_DATA"; 241 242 // extras for a TTS engine's check data activity 243 /** 244 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where 245 * the TextToSpeech engine specifies the path to its resources. 246 */ 247 public static final String EXTRA_VOICE_DATA_ROOT_DIRECTORY = "dataRoot"; 248 /** 249 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where 250 * the TextToSpeech engine specifies the file names of its resources under the 251 * resource path. 252 */ 253 public static final String EXTRA_VOICE_DATA_FILES = "dataFiles"; 254 /** 255 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where 256 * the TextToSpeech engine specifies the locale associated with each resource file. 257 */ 258 public static final String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo"; 259 /** 260 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where 261 * the TextToSpeech engine returns an ArrayList<String> of all the available voices. 262 * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are 263 * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE"). 264 * {@hide} 265 */ 266 public static final String EXTRA_AVAILABLE_VOICES = "availableVoices"; 267 /** 268 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where 269 * the TextToSpeech engine returns an ArrayList<String> of all the unavailable voices. 270 * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are 271 * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE"). 272 * {@hide} 273 */ 274 public static final String EXTRA_UNAVAILABLE_VOICES = "unavailableVoices"; 275 /** 276 * Extra information sent with the {@link #ACTION_CHECK_TTS_DATA} intent where the 277 * caller indicates to the TextToSpeech engine which specific sets of voice data to 278 * check for by sending an ArrayList<String> of the voices that are of interest. 279 * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are 280 * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE"). 281 * {@hide} 282 */ 283 public static final String EXTRA_CHECK_VOICE_DATA_FOR = "checkVoiceDataFor"; 284 285 // extras for a TTS engine's data installation 286 /** 287 * Extra information received with the {@link #ACTION_TTS_DATA_INSTALLED} intent. 288 * It indicates whether the data files for the synthesis engine were successfully 289 * installed. The installation was initiated with the {@link #ACTION_INSTALL_TTS_DATA} 290 * intent. The possible values for this extra are 291 * {@link TextToSpeech#SUCCESS} and {@link TextToSpeech#ERROR}. 292 */ 293 public static final String EXTRA_TTS_DATA_INSTALLED = "dataInstalled"; 294 295 // keys for the parameters passed with speak commands. Hidden keys are used internally 296 // to maintain engine state for each TextToSpeech instance. 297 /** 298 * {@hide} 299 */ 300 public static final String KEY_PARAM_RATE = "rate"; 301 /** 302 * {@hide} 303 */ 304 public static final String KEY_PARAM_LANGUAGE = "language"; 305 /** 306 * {@hide} 307 */ 308 public static final String KEY_PARAM_COUNTRY = "country"; 309 /** 310 * {@hide} 311 */ 312 public static final String KEY_PARAM_VARIANT = "variant"; 313 /** 314 * {@hide} 315 */ 316 public static final String KEY_PARAM_ENGINE = "engine"; 317 /** 318 * Parameter key to specify the audio stream type to be used when speaking text 319 * or playing back a file. 320 * @see TextToSpeech#speak(String, int, HashMap) 321 * @see TextToSpeech#playEarcon(String, int, HashMap) 322 */ 323 public static final String KEY_PARAM_STREAM = "streamType"; 324 /** 325 * Parameter key to identify an utterance in the 326 * {@link TextToSpeech.OnUtteranceCompletedListener} after text has been 327 * spoken, a file has been played back or a silence duration has elapsed. 328 * @see TextToSpeech#speak(String, int, HashMap) 329 * @see TextToSpeech#playEarcon(String, int, HashMap) 330 * @see TextToSpeech#synthesizeToFile(String, HashMap, String) 331 */ 332 public static final String KEY_PARAM_UTTERANCE_ID = "utteranceId"; 333 334 // key positions in the array of cached parameters 335 /** 336 * {@hide} 337 */ 338 protected static final int PARAM_POSITION_RATE = 0; 339 /** 340 * {@hide} 341 */ 342 protected static final int PARAM_POSITION_LANGUAGE = 2; 343 /** 344 * {@hide} 345 */ 346 protected static final int PARAM_POSITION_COUNTRY = 4; 347 /** 348 * {@hide} 349 */ 350 protected static final int PARAM_POSITION_VARIANT = 6; 351 /** 352 * {@hide} 353 */ 354 protected static final int PARAM_POSITION_STREAM = 8; 355 /** 356 * {@hide} 357 */ 358 protected static final int PARAM_POSITION_UTTERANCE_ID = 10; 359 360 /** 361 * {@hide} 362 */ 363 protected static final int PARAM_POSITION_ENGINE = 12; 364 365 /** 366 * {@hide} 367 */ 368 protected static final int NB_CACHED_PARAMS = 7; 369 } 370 371 /** 372 * Connection needed for the TTS. 373 */ 374 private ServiceConnection mServiceConnection; 375 376 private ITts mITts = null; 377 private ITtsCallback mITtscallback = null; 378 private Context mContext = null; 379 private String mPackageName = ""; 380 private OnInitListener mInitListener = null; 381 private boolean mStarted = false; 382 private final Object mStartLock = new Object(); 383 /** 384 * Used to store the cached parameters sent along with each synthesis request to the 385 * TTS service. 386 */ 387 private String[] mCachedParams; 388 389 /** 390 * The constructor for the TextToSpeech class. 391 * This will also initialize the associated TextToSpeech engine if it isn't already running. 392 * 393 * @param context 394 * The context this instance is running in. 395 * @param listener 396 * The {@link TextToSpeech.OnInitListener} that will be called when the 397 * TextToSpeech engine has initialized. 398 */ 399 public TextToSpeech(Context context, OnInitListener listener) { 400 mContext = context; 401 mPackageName = mContext.getPackageName(); 402 mInitListener = listener; 403 404 mCachedParams = new String[2*Engine.NB_CACHED_PARAMS]; // store key and value 405 mCachedParams[Engine.PARAM_POSITION_RATE] = Engine.KEY_PARAM_RATE; 406 mCachedParams[Engine.PARAM_POSITION_LANGUAGE] = Engine.KEY_PARAM_LANGUAGE; 407 mCachedParams[Engine.PARAM_POSITION_COUNTRY] = Engine.KEY_PARAM_COUNTRY; 408 mCachedParams[Engine.PARAM_POSITION_VARIANT] = Engine.KEY_PARAM_VARIANT; 409 mCachedParams[Engine.PARAM_POSITION_STREAM] = Engine.KEY_PARAM_STREAM; 410 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID] = Engine.KEY_PARAM_UTTERANCE_ID; 411 mCachedParams[Engine.PARAM_POSITION_ENGINE] = Engine.KEY_PARAM_ENGINE; 412 413 // Leave all defaults that are shown in Settings uninitialized so that 414 // the values set in Settings will take effect if the application does 415 // not try to change these settings itself. 416 mCachedParams[Engine.PARAM_POSITION_RATE + 1] = ""; 417 mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = ""; 418 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = ""; 419 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = ""; 420 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = 421 String.valueOf(Engine.DEFAULT_STREAM); 422 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = ""; 423 mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = ""; 424 425 initTts(); 426 } 427 428 429 private void initTts() { 430 mStarted = false; 431 432 // Initialize the TTS, run the callback after the binding is successful 433 mServiceConnection = new ServiceConnection() { 434 public void onServiceConnected(ComponentName name, IBinder service) { 435 synchronized(mStartLock) { 436 mITts = ITts.Stub.asInterface(service); 437 mStarted = true; 438 if (mInitListener != null) { 439 // TODO manage failures and missing resources 440 mInitListener.onInit(SUCCESS); 441 } 442 } 443 } 444 445 public void onServiceDisconnected(ComponentName name) { 446 synchronized(mStartLock) { 447 mITts = null; 448 mInitListener = null; 449 mStarted = false; 450 } 451 } 452 }; 453 454 Intent intent = new Intent("android.intent.action.START_TTS_SERVICE"); 455 intent.addCategory("android.intent.category.TTS"); 456 mContext.bindService(intent, mServiceConnection, 457 Context.BIND_AUTO_CREATE); 458 // TODO handle case where the binding works (should always work) but 459 // the plugin fails 460 } 461 462 463 /** 464 * Releases the resources used by the TextToSpeech engine. 465 * It is good practice for instance to call this method in the onDestroy() method of an Activity 466 * so the TextToSpeech engine can be cleanly stopped. 467 */ 468 public void shutdown() { 469 try { 470 mContext.unbindService(mServiceConnection); 471 } catch (IllegalArgumentException e) { 472 // Do nothing and fail silently since an error here indicates that 473 // binding never succeeded in the first place. 474 } 475 } 476 477 478 /** 479 * Adds a mapping between a string of text and a sound resource in a 480 * package. After a call to this method, subsequent calls to 481 * {@link #speak(String, int, HashMap)} will play the specified sound resource 482 * if it is available, or synthesize the text it is missing. 483 * 484 * @param text 485 * The string of text. Example: <code>"south_south_east"</code> 486 * 487 * @param packagename 488 * Pass the packagename of the application that contains the 489 * resource. If the resource is in your own application (this is 490 * the most common case), then put the packagename of your 491 * application here.<br/> 492 * Example: <b>"com.google.marvin.compass"</b><br/> 493 * The packagename can be found in the AndroidManifest.xml of 494 * your application. 495 * <p> 496 * <code><manifest xmlns:android="..." 497 * package="<b>com.google.marvin.compass</b>"></code> 498 * </p> 499 * 500 * @param resourceId 501 * Example: <code>R.raw.south_south_east</code> 502 * 503 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 504 */ 505 public int addSpeech(String text, String packagename, int resourceId) { 506 synchronized(mStartLock) { 507 if (!mStarted) { 508 return ERROR; 509 } 510 try { 511 mITts.addSpeech(mPackageName, text, packagename, resourceId); 512 return SUCCESS; 513 } catch (RemoteException e) { 514 // TTS died; restart it. 515 Log.e("TextToSpeech.java - addSpeech", "RemoteException"); 516 e.printStackTrace(); 517 mStarted = false; 518 initTts(); 519 } catch (NullPointerException e) { 520 // TTS died; restart it. 521 Log.e("TextToSpeech.java - addSpeech", "NullPointerException"); 522 e.printStackTrace(); 523 mStarted = false; 524 initTts(); 525 } catch (IllegalStateException e) { 526 // TTS died; restart it. 527 Log.e("TextToSpeech.java - addSpeech", "IllegalStateException"); 528 e.printStackTrace(); 529 mStarted = false; 530 initTts(); 531 } 532 return ERROR; 533 } 534 } 535 536 537 /** 538 * Adds a mapping between a string of text and a sound file. Using this, it 539 * is possible to add custom pronounciations for a string of text. 540 * After a call to this method, subsequent calls to {@link #speak(String, int, HashMap)} 541 * will play the specified sound resource if it is available, or synthesize the text it is 542 * missing. 543 * 544 * @param text 545 * The string of text. Example: <code>"south_south_east"</code> 546 * @param filename 547 * The full path to the sound file (for example: 548 * "/sdcard/mysounds/hello.wav") 549 * 550 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 551 */ 552 public int addSpeech(String text, String filename) { 553 synchronized (mStartLock) { 554 if (!mStarted) { 555 return ERROR; 556 } 557 try { 558 mITts.addSpeechFile(mPackageName, text, filename); 559 return SUCCESS; 560 } catch (RemoteException e) { 561 // TTS died; restart it. 562 Log.e("TextToSpeech.java - addSpeech", "RemoteException"); 563 e.printStackTrace(); 564 mStarted = false; 565 initTts(); 566 } catch (NullPointerException e) { 567 // TTS died; restart it. 568 Log.e("TextToSpeech.java - addSpeech", "NullPointerException"); 569 e.printStackTrace(); 570 mStarted = false; 571 initTts(); 572 } catch (IllegalStateException e) { 573 // TTS died; restart it. 574 Log.e("TextToSpeech.java - addSpeech", "IllegalStateException"); 575 e.printStackTrace(); 576 mStarted = false; 577 initTts(); 578 } 579 return ERROR; 580 } 581 } 582 583 584 /** 585 * Adds a mapping between a string of text and a sound resource in a 586 * package. Use this to add custom earcons. 587 * 588 * @see #playEarcon(String, int, HashMap) 589 * 590 * @param earcon The name of the earcon. 591 * Example: <code>"[tick]"</code><br/> 592 * 593 * @param packagename 594 * the package name of the application that contains the 595 * resource. This can for instance be the package name of your own application. 596 * Example: <b>"com.google.marvin.compass"</b><br/> 597 * The package name can be found in the AndroidManifest.xml of 598 * the application containing the resource. 599 * <p> 600 * <code><manifest xmlns:android="..." 601 * package="<b>com.google.marvin.compass</b>"></code> 602 * </p> 603 * 604 * @param resourceId 605 * Example: <code>R.raw.tick_snd</code> 606 * 607 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 608 */ 609 public int addEarcon(String earcon, String packagename, int resourceId) { 610 synchronized(mStartLock) { 611 if (!mStarted) { 612 return ERROR; 613 } 614 try { 615 mITts.addEarcon(mPackageName, earcon, packagename, resourceId); 616 return SUCCESS; 617 } catch (RemoteException e) { 618 // TTS died; restart it. 619 Log.e("TextToSpeech.java - addEarcon", "RemoteException"); 620 e.printStackTrace(); 621 mStarted = false; 622 initTts(); 623 } catch (NullPointerException e) { 624 // TTS died; restart it. 625 Log.e("TextToSpeech.java - addEarcon", "NullPointerException"); 626 e.printStackTrace(); 627 mStarted = false; 628 initTts(); 629 } catch (IllegalStateException e) { 630 // TTS died; restart it. 631 Log.e("TextToSpeech.java - addEarcon", "IllegalStateException"); 632 e.printStackTrace(); 633 mStarted = false; 634 initTts(); 635 } 636 return ERROR; 637 } 638 } 639 640 641 /** 642 * Adds a mapping between a string of text and a sound file. 643 * Use this to add custom earcons. 644 * 645 * @see #playEarcon(String, int, HashMap) 646 * 647 * @param earcon 648 * The name of the earcon. 649 * Example: <code>"[tick]"</code> 650 * @param filename 651 * The full path to the sound file (for example: 652 * "/sdcard/mysounds/tick.wav") 653 * 654 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 655 */ 656 public int addEarcon(String earcon, String filename) { 657 synchronized (mStartLock) { 658 if (!mStarted) { 659 return ERROR; 660 } 661 try { 662 mITts.addEarconFile(mPackageName, earcon, filename); 663 return SUCCESS; 664 } catch (RemoteException e) { 665 // TTS died; restart it. 666 Log.e("TextToSpeech.java - addEarcon", "RemoteException"); 667 e.printStackTrace(); 668 mStarted = false; 669 initTts(); 670 } catch (NullPointerException e) { 671 // TTS died; restart it. 672 Log.e("TextToSpeech.java - addEarcon", "NullPointerException"); 673 e.printStackTrace(); 674 mStarted = false; 675 initTts(); 676 } catch (IllegalStateException e) { 677 // TTS died; restart it. 678 Log.e("TextToSpeech.java - addEarcon", "IllegalStateException"); 679 e.printStackTrace(); 680 mStarted = false; 681 initTts(); 682 } 683 return ERROR; 684 } 685 } 686 687 688 /** 689 * Speaks the string using the specified queuing strategy and speech 690 * parameters. 691 * 692 * @param text 693 * The string of text to be spoken. 694 * @param queueMode 695 * The queuing strategy to use. 696 * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. 697 * @param params 698 * The list of parameters to be used. Can be null if no parameters are given. 699 * They are specified using a (key, value) pair, where the key can be 700 * {@link Engine#KEY_PARAM_STREAM} or 701 * {@link Engine#KEY_PARAM_UTTERANCE_ID}. 702 * 703 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 704 */ 705 public int speak(String text, int queueMode, HashMap<String,String> params) 706 { 707 synchronized (mStartLock) { 708 int result = ERROR; 709 Log.i("TTS received: ", text); 710 if (!mStarted) { 711 return result; 712 } 713 try { 714 if ((params != null) && (!params.isEmpty())) { 715 String extra = params.get(Engine.KEY_PARAM_STREAM); 716 if (extra != null) { 717 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = extra; 718 } 719 extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID); 720 if (extra != null) { 721 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra; 722 } 723 extra = params.get(Engine.KEY_PARAM_ENGINE); 724 if (extra != null) { 725 mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = extra; 726 } 727 } 728 result = mITts.speak(mPackageName, text, queueMode, mCachedParams); 729 } catch (RemoteException e) { 730 // TTS died; restart it. 731 Log.e("TextToSpeech.java - speak", "RemoteException"); 732 e.printStackTrace(); 733 mStarted = false; 734 initTts(); 735 } catch (NullPointerException e) { 736 // TTS died; restart it. 737 Log.e("TextToSpeech.java - speak", "NullPointerException"); 738 e.printStackTrace(); 739 mStarted = false; 740 initTts(); 741 } catch (IllegalStateException e) { 742 // TTS died; restart it. 743 Log.e("TextToSpeech.java - speak", "IllegalStateException"); 744 e.printStackTrace(); 745 mStarted = false; 746 initTts(); 747 } finally { 748 resetCachedParams(); 749 return result; 750 } 751 } 752 } 753 754 755 /** 756 * Plays the earcon using the specified queueing mode and parameters. 757 * 758 * @param earcon 759 * The earcon that should be played 760 * @param queueMode 761 * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. 762 * @param params 763 * The list of parameters to be used. Can be null if no parameters are given. 764 * They are specified using a (key, value) pair, where the key can be 765 * {@link Engine#KEY_PARAM_STREAM} or 766 * {@link Engine#KEY_PARAM_UTTERANCE_ID}. 767 * 768 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 769 */ 770 public int playEarcon(String earcon, int queueMode, 771 HashMap<String,String> params) { 772 synchronized (mStartLock) { 773 int result = ERROR; 774 if (!mStarted) { 775 return result; 776 } 777 try { 778 if ((params != null) && (!params.isEmpty())) { 779 String extra = params.get(Engine.KEY_PARAM_STREAM); 780 if (extra != null) { 781 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = extra; 782 } 783 extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID); 784 if (extra != null) { 785 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra; 786 } 787 } 788 result = mITts.playEarcon(mPackageName, earcon, queueMode, null); 789 } catch (RemoteException e) { 790 // TTS died; restart it. 791 Log.e("TextToSpeech.java - playEarcon", "RemoteException"); 792 e.printStackTrace(); 793 mStarted = false; 794 initTts(); 795 } catch (NullPointerException e) { 796 // TTS died; restart it. 797 Log.e("TextToSpeech.java - playEarcon", "NullPointerException"); 798 e.printStackTrace(); 799 mStarted = false; 800 initTts(); 801 } catch (IllegalStateException e) { 802 // TTS died; restart it. 803 Log.e("TextToSpeech.java - playEarcon", "IllegalStateException"); 804 e.printStackTrace(); 805 mStarted = false; 806 initTts(); 807 } finally { 808 resetCachedParams(); 809 return result; 810 } 811 } 812 } 813 814 /** 815 * Plays silence for the specified amount of time using the specified 816 * queue mode. 817 * 818 * @param durationInMs 819 * A long that indicates how long the silence should last. 820 * @param queueMode 821 * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. 822 * @param params 823 * The list of parameters to be used. Can be null if no parameters are given. 824 * They are specified using a (key, value) pair, where the key can be 825 * {@link Engine#KEY_PARAM_UTTERANCE_ID}. 826 * 827 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 828 */ 829 public int playSilence(long durationInMs, int queueMode, HashMap<String,String> params) { 830 synchronized (mStartLock) { 831 int result = ERROR; 832 if (!mStarted) { 833 return result; 834 } 835 try { 836 if ((params != null) && (!params.isEmpty())) { 837 String extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID); 838 if (extra != null) { 839 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra; 840 } 841 } 842 result = mITts.playSilence(mPackageName, durationInMs, queueMode, mCachedParams); 843 } catch (RemoteException e) { 844 // TTS died; restart it. 845 Log.e("TextToSpeech.java - playSilence", "RemoteException"); 846 e.printStackTrace(); 847 mStarted = false; 848 initTts(); 849 } catch (NullPointerException e) { 850 // TTS died; restart it. 851 Log.e("TextToSpeech.java - playSilence", "NullPointerException"); 852 e.printStackTrace(); 853 mStarted = false; 854 initTts(); 855 } catch (IllegalStateException e) { 856 // TTS died; restart it. 857 Log.e("TextToSpeech.java - playSilence", "IllegalStateException"); 858 e.printStackTrace(); 859 mStarted = false; 860 initTts(); 861 } finally { 862 return result; 863 } 864 } 865 } 866 867 868 /** 869 * Returns whether or not the TextToSpeech engine is busy speaking. 870 * 871 * @return Whether or not the TextToSpeech engine is busy speaking. 872 */ 873 public boolean isSpeaking() { 874 synchronized (mStartLock) { 875 if (!mStarted) { 876 return false; 877 } 878 try { 879 return mITts.isSpeaking(); 880 } catch (RemoteException e) { 881 // TTS died; restart it. 882 Log.e("TextToSpeech.java - isSpeaking", "RemoteException"); 883 e.printStackTrace(); 884 mStarted = false; 885 initTts(); 886 } catch (NullPointerException e) { 887 // TTS died; restart it. 888 Log.e("TextToSpeech.java - isSpeaking", "NullPointerException"); 889 e.printStackTrace(); 890 mStarted = false; 891 initTts(); 892 } catch (IllegalStateException e) { 893 // TTS died; restart it. 894 Log.e("TextToSpeech.java - isSpeaking", "IllegalStateException"); 895 e.printStackTrace(); 896 mStarted = false; 897 initTts(); 898 } 899 return false; 900 } 901 } 902 903 904 /** 905 * Interrupts the current utterance (whether played or rendered to file) and discards other 906 * utterances in the queue. 907 * 908 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 909 */ 910 public int stop() { 911 synchronized (mStartLock) { 912 int result = ERROR; 913 if (!mStarted) { 914 return result; 915 } 916 try { 917 result = mITts.stop(mPackageName); 918 } catch (RemoteException e) { 919 // TTS died; restart it. 920 Log.e("TextToSpeech.java - stop", "RemoteException"); 921 e.printStackTrace(); 922 mStarted = false; 923 initTts(); 924 } catch (NullPointerException e) { 925 // TTS died; restart it. 926 Log.e("TextToSpeech.java - stop", "NullPointerException"); 927 e.printStackTrace(); 928 mStarted = false; 929 initTts(); 930 } catch (IllegalStateException e) { 931 // TTS died; restart it. 932 Log.e("TextToSpeech.java - stop", "IllegalStateException"); 933 e.printStackTrace(); 934 mStarted = false; 935 initTts(); 936 } finally { 937 return result; 938 } 939 } 940 } 941 942 943 /** 944 * Sets the speech rate for the TextToSpeech engine. 945 * 946 * This has no effect on any pre-recorded speech. 947 * 948 * @param speechRate 949 * The speech rate for the TextToSpeech engine. 1 is the normal speed, 950 * lower values slow down the speech (0.5 is half the normal speech rate), 951 * greater values accelerate it (2 is twice the normal speech rate). 952 * 953 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 954 */ 955 public int setSpeechRate(float speechRate) { 956 synchronized (mStartLock) { 957 int result = ERROR; 958 if (!mStarted) { 959 return result; 960 } 961 try { 962 if (speechRate > 0) { 963 int rate = (int)(speechRate*100); 964 mCachedParams[Engine.PARAM_POSITION_RATE + 1] = String.valueOf(rate); 965 // the rate is not set here, instead it is cached so it will be associated 966 // with all upcoming utterances. 967 if (speechRate > 0.0f) { 968 result = SUCCESS; 969 } else { 970 result = ERROR; 971 } 972 } 973 } catch (NullPointerException e) { 974 // TTS died; restart it. 975 Log.e("TextToSpeech.java - setSpeechRate", "NullPointerException"); 976 e.printStackTrace(); 977 mStarted = false; 978 initTts(); 979 } catch (IllegalStateException e) { 980 // TTS died; restart it. 981 Log.e("TextToSpeech.java - setSpeechRate", "IllegalStateException"); 982 e.printStackTrace(); 983 mStarted = false; 984 initTts(); 985 } finally { 986 return result; 987 } 988 } 989 } 990 991 992 /** 993 * Sets the speech pitch for the TextToSpeech engine. 994 * 995 * This has no effect on any pre-recorded speech. 996 * 997 * @param pitch 998 * The pitch for the TextToSpeech engine. 1 is the normal pitch, 999 * lower values lower the tone of the synthesized voice, 1000 * greater values increase it. 1001 * 1002 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1003 */ 1004 public int setPitch(float pitch) { 1005 synchronized (mStartLock) { 1006 int result = ERROR; 1007 if (!mStarted) { 1008 return result; 1009 } 1010 try { 1011 if (pitch > 0) { 1012 result = mITts.setPitch(mPackageName, (int)(pitch*100)); 1013 } 1014 } catch (RemoteException e) { 1015 // TTS died; restart it. 1016 Log.e("TextToSpeech.java - setPitch", "RemoteException"); 1017 e.printStackTrace(); 1018 mStarted = false; 1019 initTts(); 1020 } catch (NullPointerException e) { 1021 // TTS died; restart it. 1022 Log.e("TextToSpeech.java - setPitch", "NullPointerException"); 1023 e.printStackTrace(); 1024 mStarted = false; 1025 initTts(); 1026 } catch (IllegalStateException e) { 1027 // TTS died; restart it. 1028 Log.e("TextToSpeech.java - setPitch", "IllegalStateException"); 1029 e.printStackTrace(); 1030 mStarted = false; 1031 initTts(); 1032 } finally { 1033 return result; 1034 } 1035 } 1036 } 1037 1038 1039 /** 1040 * Sets the language for the TextToSpeech engine. 1041 * The TextToSpeech engine will try to use the closest match to the specified 1042 * language as represented by the Locale, but there is no guarantee that the exact same Locale 1043 * will be used. Use {@link #isLanguageAvailable(Locale)} to check the level of support 1044 * before choosing the language to use for the next utterances. 1045 * 1046 * @param loc 1047 * The locale describing the language to be used. 1048 * 1049 * @return code indicating the support status for the locale. See {@link #LANG_AVAILABLE}, 1050 * {@link #LANG_COUNTRY_AVAILABLE}, {@link #LANG_COUNTRY_VAR_AVAILABLE}, 1051 * {@link #LANG_MISSING_DATA} and {@link #LANG_NOT_SUPPORTED}. 1052 */ 1053 public int setLanguage(Locale loc) { 1054 synchronized (mStartLock) { 1055 int result = LANG_NOT_SUPPORTED; 1056 if (!mStarted) { 1057 return result; 1058 } 1059 try { 1060 mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = loc.getISO3Language(); 1061 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = loc.getISO3Country(); 1062 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = loc.getVariant(); 1063 // the language is not set here, instead it is cached so it will be associated 1064 // with all upcoming utterances. But we still need to report the language support, 1065 // which is achieved by calling isLanguageAvailable() 1066 result = mITts.isLanguageAvailable( 1067 mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1], 1068 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1], 1069 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] ); 1070 } catch (RemoteException e) { 1071 // TTS died; restart it. 1072 Log.e("TextToSpeech.java - setLanguage", "RemoteException"); 1073 e.printStackTrace(); 1074 mStarted = false; 1075 initTts(); 1076 } catch (NullPointerException e) { 1077 // TTS died; restart it. 1078 Log.e("TextToSpeech.java - setLanguage", "NullPointerException"); 1079 e.printStackTrace(); 1080 mStarted = false; 1081 initTts(); 1082 } catch (IllegalStateException e) { 1083 // TTS died; restart it. 1084 Log.e("TextToSpeech.java - setLanguage", "IllegalStateException"); 1085 e.printStackTrace(); 1086 mStarted = false; 1087 initTts(); 1088 } finally { 1089 return result; 1090 } 1091 } 1092 } 1093 1094 1095 /** 1096 * Returns a Locale instance describing the language currently being used by the TextToSpeech 1097 * engine. 1098 * @return language, country (if any) and variant (if any) used by the engine stored in a Locale 1099 * instance, or null is the TextToSpeech engine has failed. 1100 */ 1101 public Locale getLanguage() { 1102 synchronized (mStartLock) { 1103 if (!mStarted) { 1104 return null; 1105 } 1106 try { 1107 String[] locStrings = mITts.getLanguage(); 1108 if ((locStrings != null) && (locStrings.length == 3)) { 1109 return new Locale(locStrings[0], locStrings[1], locStrings[2]); 1110 } else { 1111 return null; 1112 } 1113 } catch (RemoteException e) { 1114 // TTS died; restart it. 1115 Log.e("TextToSpeech.java - getLanguage", "RemoteException"); 1116 e.printStackTrace(); 1117 mStarted = false; 1118 initTts(); 1119 } catch (NullPointerException e) { 1120 // TTS died; restart it. 1121 Log.e("TextToSpeech.java - getLanguage", "NullPointerException"); 1122 e.printStackTrace(); 1123 mStarted = false; 1124 initTts(); 1125 } catch (IllegalStateException e) { 1126 // TTS died; restart it. 1127 Log.e("TextToSpeech.java - getLanguage", "IllegalStateException"); 1128 e.printStackTrace(); 1129 mStarted = false; 1130 initTts(); 1131 } 1132 return null; 1133 } 1134 } 1135 1136 /** 1137 * Checks if the specified language as represented by the Locale is available and supported. 1138 * 1139 * @param loc 1140 * The Locale describing the language to be used. 1141 * 1142 * @return code indicating the support status for the locale. See {@link #LANG_AVAILABLE}, 1143 * {@link #LANG_COUNTRY_AVAILABLE}, {@link #LANG_COUNTRY_VAR_AVAILABLE}, 1144 * {@link #LANG_MISSING_DATA} and {@link #LANG_NOT_SUPPORTED}. 1145 */ 1146 public int isLanguageAvailable(Locale loc) { 1147 synchronized (mStartLock) { 1148 int result = LANG_NOT_SUPPORTED; 1149 if (!mStarted) { 1150 return result; 1151 } 1152 try { 1153 result = mITts.isLanguageAvailable(loc.getISO3Language(), 1154 loc.getISO3Country(), loc.getVariant()); 1155 } catch (RemoteException e) { 1156 // TTS died; restart it. 1157 Log.e("TextToSpeech.java - isLanguageAvailable", "RemoteException"); 1158 e.printStackTrace(); 1159 mStarted = false; 1160 initTts(); 1161 } catch (NullPointerException e) { 1162 // TTS died; restart it. 1163 Log.e("TextToSpeech.java - isLanguageAvailable", "NullPointerException"); 1164 e.printStackTrace(); 1165 mStarted = false; 1166 initTts(); 1167 } catch (IllegalStateException e) { 1168 // TTS died; restart it. 1169 Log.e("TextToSpeech.java - isLanguageAvailable", "IllegalStateException"); 1170 e.printStackTrace(); 1171 mStarted = false; 1172 initTts(); 1173 } finally { 1174 return result; 1175 } 1176 } 1177 } 1178 1179 1180 /** 1181 * Synthesizes the given text to a file using the specified parameters. 1182 * 1183 * @param text 1184 * The String of text that should be synthesized 1185 * @param params 1186 * The list of parameters to be used. Can be null if no parameters are given. 1187 * They are specified using a (key, value) pair, where the key can be 1188 * {@link Engine#KEY_PARAM_UTTERANCE_ID}. 1189 * @param filename 1190 * The string that gives the full output filename; it should be 1191 * something like "/sdcard/myappsounds/mysound.wav". 1192 * 1193 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1194 */ 1195 public int synthesizeToFile(String text, HashMap<String,String> params, 1196 String filename) { 1197 synchronized (mStartLock) { 1198 int result = ERROR; 1199 if (!mStarted) { 1200 return result; 1201 } 1202 try { 1203 if ((params != null) && (!params.isEmpty())) { 1204 // no need to read the stream type here 1205 String extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID); 1206 if (extra != null) { 1207 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra; 1208 } 1209 extra = params.get(Engine.KEY_PARAM_ENGINE); 1210 if (extra != null) { 1211 mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = extra; 1212 } 1213 } 1214 if (mITts.synthesizeToFile(mPackageName, text, mCachedParams, filename)){ 1215 result = SUCCESS; 1216 } 1217 } catch (RemoteException e) { 1218 // TTS died; restart it. 1219 Log.e("TextToSpeech.java - synthesizeToFile", "RemoteException"); 1220 e.printStackTrace(); 1221 mStarted = false; 1222 initTts(); 1223 } catch (NullPointerException e) { 1224 // TTS died; restart it. 1225 Log.e("TextToSpeech.java - synthesizeToFile", "NullPointerException"); 1226 e.printStackTrace(); 1227 mStarted = false; 1228 initTts(); 1229 } catch (IllegalStateException e) { 1230 // TTS died; restart it. 1231 Log.e("TextToSpeech.java - synthesizeToFile", "IllegalStateException"); 1232 e.printStackTrace(); 1233 mStarted = false; 1234 initTts(); 1235 } finally { 1236 resetCachedParams(); 1237 return result; 1238 } 1239 } 1240 } 1241 1242 1243 /** 1244 * Convenience method to reset the cached parameters to the current default values 1245 * if they are not persistent between calls to the service. 1246 */ 1247 private void resetCachedParams() { 1248 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = 1249 String.valueOf(Engine.DEFAULT_STREAM); 1250 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID+ 1] = ""; 1251 } 1252 1253 /** 1254 * Sets the OnUtteranceCompletedListener that will fire when an utterance completes. 1255 * 1256 * @param listener 1257 * The OnUtteranceCompletedListener 1258 * 1259 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1260 */ 1261 public int setOnUtteranceCompletedListener( 1262 final OnUtteranceCompletedListener listener) { 1263 synchronized (mStartLock) { 1264 int result = ERROR; 1265 if (!mStarted) { 1266 return result; 1267 } 1268 mITtscallback = new ITtsCallback.Stub() { 1269 public void utteranceCompleted(String utteranceId) throws RemoteException { 1270 if (listener != null) { 1271 listener.onUtteranceCompleted(utteranceId); 1272 } 1273 } 1274 }; 1275 try { 1276 result = mITts.registerCallback(mPackageName, mITtscallback); 1277 } catch (RemoteException e) { 1278 // TTS died; restart it. 1279 Log.e("TextToSpeech.java - registerCallback", "RemoteException"); 1280 e.printStackTrace(); 1281 mStarted = false; 1282 initTts(); 1283 } catch (NullPointerException e) { 1284 // TTS died; restart it. 1285 Log.e("TextToSpeech.java - registerCallback", "NullPointerException"); 1286 e.printStackTrace(); 1287 mStarted = false; 1288 initTts(); 1289 } catch (IllegalStateException e) { 1290 // TTS died; restart it. 1291 Log.e("TextToSpeech.java - registerCallback", "IllegalStateException"); 1292 e.printStackTrace(); 1293 mStarted = false; 1294 initTts(); 1295 } finally { 1296 return result; 1297 } 1298 } 1299 } 1300 1301 /** 1302 * Sets the speech synthesis engine to be used by its packagename. 1303 * 1304 * @param enginePackageName 1305 * The packagename for the synthesis engine (ie, "com.svox.pico") 1306 * 1307 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1308 */ 1309 public int setEngineByPackageName(String enginePackageName) { 1310 synchronized (mStartLock) { 1311 int result = TextToSpeech.ERROR; 1312 if (!mStarted) { 1313 return result; 1314 } 1315 try { 1316 result = mITts.setEngineByPackageName(enginePackageName); 1317 if (result == TextToSpeech.SUCCESS){ 1318 mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = enginePackageName; 1319 } 1320 } catch (RemoteException e) { 1321 // TTS died; restart it. 1322 Log.e("TextToSpeech.java - setEngineByPackageName", "RemoteException"); 1323 e.printStackTrace(); 1324 mStarted = false; 1325 initTts(); 1326 } catch (NullPointerException e) { 1327 // TTS died; restart it. 1328 Log.e("TextToSpeech.java - setEngineByPackageName", "NullPointerException"); 1329 e.printStackTrace(); 1330 mStarted = false; 1331 initTts(); 1332 } catch (IllegalStateException e) { 1333 // TTS died; restart it. 1334 Log.e("TextToSpeech.java - setEngineByPackageName", "IllegalStateException"); 1335 e.printStackTrace(); 1336 mStarted = false; 1337 initTts(); 1338 } finally { 1339 return result; 1340 } 1341 } 1342 } 1343 1344} 1345