目前只支持5种语言,分别是English、 French 、 German 、 Italian 和 Spanish.
系统要求为android 1.6以上
直接上代码啦:
[java]
public class TTSActivity extends Activity implements TextToSpeech.OnInitListener {
private static final String TAG = "TextToSpeechDemo";
private TextToSpeech mTts;//首先来个对象,至于TextToSpeech类,按F3可以查看
[java]
//TODO complete javadoc + add links to constants
public class TextToSpeech {
/**
* Denotes a successful operation.
*/
public static final int SUCCESS = 0;
/**
* Denotes a generic operation failure.
*/
public static final int ERROR = -1;
以上只包含部分代码,其他的就省略了。
[java]
mTts = new TextToSpeech(this,
this // TextToSpeech.OnInitListener
);
然后是实例化,构造函数参数也可以F3一下
[java]
public TextToSpeech(Context context, OnInitListener listener) {
mContext = context;
mPackageName = mContext.getPackageName();
mInitListener = listener;
mCachedParams = new String[2*Engine.NB_CACHED_PARAMS]; // store key and value
mCachedParams[Engine.PARAM_POSITION_RATE] = Engine.KEY_PARAM_RATE;
mCachedParams[Engine.PARAM_POSITION_LANGUAGE] = Engine.KEY_PARAM_LANGUAGE;
mCachedParams[Engine.PARAM_POSITION_COUNTRY] = Engine.KEY_PARAM_COUNTRY;
mCachedParams[Engine.PARAM_POSITION_VARIANT] = Engine.KEY_PARAM_VARIANT;
mCachedParams[Engine.PARAM_POSITION_STREAM] = Engine.KEY_PARAM_STREAM;
mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID] = Engine.KEY_PARAM_UTTERANCE_ID;
mCachedParams[Engine.PARAM_POSITION_RATE + 1] =
String.valueOf(Engine.DEFAULT_RATE);
// initialize the language cached parameters with the current Locale
Locale defaultLoc = Locale.getDefault();
mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = defaultLoc.getISO3Language();
mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = defaultLoc.getISO3Country();
mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = defaultLoc.getVariant();
mCachedParams[Engine.PARAM_POSITION_STREAM + 1] =
String.valueOf(Engine.DEFAULT_STREAM);
mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = "";
initTts();
}
context也就是那个Activity
[java]
public abstract class Context {
/**
* File creation mode: the default mode, where the created file can only
* be accessed by the calling application (or all applications sharing the
* same user ID).
* @see #MODE_WORLD_READABLE
* @see #MODE_WORLD_WRITEABLE
*/
public static final int MODE_PRIVATE = 0x0000;
/**
* File creation mode: allow all other applications to have read access
* to the created file.
* @see #MODE_PRIVATE
* @see #MODE_WORLD_WRITEABLE
*/
public static final int MODE_WORLD_READABLE = 0x0001;
/**
* File creation mode: allow all other applications to have write access
* to the created file.
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
*/
listener是个初始化监听接口
[java]
/**
* Called when the TTS has initialized.
*
* The InitListener must implement the onInit function. onInit is passed a
* status code indicating the result of the TTS initialization.
*/
public interface OnInitListener {
public void onInit(int status);
}
implements Listener代码如下:(这是APIDemo里面的)
[java]
// Implements TextToSpeech.OnInitListener.
public void onInit(int status) {
// status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR.
if (status == TextToSpeech.SUCCESS) {
// Set preferred language to US english.
// Note that a language may not be available, and the result will indicate this.
int result = mTts.setLanguage(Locale.US);
// Try this someday for some interesting results.
// int result mTts.setLanguage(Locale.FRANCE);
if (result == TextToSpeech.LANG_MISSING_DATA ||
result == TextToSpeech.LANG_NOT_SUPPORTED) {
// Lanuage data is missing or the language is not supported.
Log.e(TAG, "Language is not available.");
} else {
// Check the documentation for other possible result codes.
// For example, the language may be available for the locale,
// but not for the specified country and variant.
// The TTS engine has been successfully initialized.
// Allow the user to press the button for the app to speak again.
mAgainButton.setEnabled(true);
// Greet the user.
sayHello();
}
} else {
// Initialization failed.
Log.e(TAG, "Could not initialize TextToSpeech.");
}
}
status这个在构造函数中赋值,(Ctrl+F可以在源码中找到)
[java]
mCachedParams[Engine.PARAM_POSITION_STREAM + 1] =
String.valueOf(Engine.DEFAULT_STREAM);
mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = "";
initTts();//构造函数最后这个地方
}
private void initTts() {
mStarted = false;
// Initialize the TTS, run the callback after the binding is successful
mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized(mStartLock) {
mITts = ITts.Stub.asInterface(service);
mStarted = true;
if (mInitListener != null) {
// TODO manage failures and missing resources
mInitListener.onInit(SUCCESS);//这里给status赋值
}
}
}
setLanguage方法源码:
[java]
public int setLanguage(Locale loc) {
synchronized (mStartLock) {
int result = LANG_NOT_SUPPORTED;
if (!mStarted) {
return result;
}
try {
mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = loc.getISO3Language();
mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = loc.getISO3Country();
mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = loc.getVariant();
// the language is not set here, instead it is cached so it will be associated
// with all upcoming utterances. But we still need to report the language support,
// which is achieved by calling isLanguageAvailable()
result = mITts.isLanguageAvailable(
mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1],
mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1],
mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] );
} catch (RemoteException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - setLanguage", "RemoteException");
e.printStackTrace();
mStarted = false;
initTts();
} catch (NullPointerException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - setLanguage", "NullPointerException");
e.printStackTrace();
mStarted = false;
initTts();
} catch (IllegalStateException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - setLanguage", "IllegalStateException");
e.printStackTrace();
mStarted = false;
initTts();
} finally {
return result;
}
}
}
Locale.US定义如下:
[java]
public static final Locale UK = new Locale("en", "GB"); //$NON-NLS-1$ //$NON-NLS-2$
/**
* Locale constant for en_US.
*
* @since Android 1.0
*/
public static final Locale US = new Locale("en", "US"); //$NON-NLS-1$//$NON-NLS-2$
Locale构造器源码:
[java] view plaincopy
<EMBED id=ZeroClipboardMovie_11 name=ZeroClipboardMovie_11 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=11&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
/**
* Constructs a new {@code Locale} using the specified language and country codes.
*
* @param language
* the language this {@code Locale} represents.
* @param country
* the country this {@code Locale} represents.
* @since Android 1.0
*/
public Locale(String language, String country) {
this(language, country, ""); //$NON-NLS-1$
}
这里每按一次按钮就有一个Speech
[java]
private void sayHello() {
String left = "Please turn left";
String right="Please turn right";
if(mDirection==0){
mTts.speak(left,
TextToSpeech.QUEUE_FLUSH, // Drop all pending entries in the playback queue.
null);
mDirection=1;
}else{
mTts.speak(right, TextToSpeech.QUEUE_FLUSH, null);
mDirection=0;
}
speak函数源码:各参数都有相应的解释,我就不啰嗦了
[java]
/**
* Speaks the string using the specified queuing strategy and speech
* parameters. Note that the speech parameters are not universally supported
* by all engines and will be treated as a hint. The TTS library will try to
* fulfill these parameters as much as possible, but there is no guarantee
* that the voice used will have the properties specified.
*
* @param text
* The string of text to be spoken.
* @param queueMode
* The queuing strategy to use.
* See QUEUE_ADD and QUEUE_FLUSH.
* @param params
* The hashmap of speech parameters to be used.
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int speak(String text, int queueMode, HashMap<String,String> params)
{
synchronized (mStartLock) {
int result = ERROR;
Log.i("TTS received: ", text);
if (!mStarted) {
return result;
}
try {
if ((params != null) && (!params.isEmpty())) {
String extra = params.get(Engine.KEY_PARAM_STREAM);
if (extra != null) {
mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = extra;
}
extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
if (extra != null) {
mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
}
}
result = mITts.speak(mPackageName, text, queueMode, mCachedParams);
} catch (RemoteException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - speak", "RemoteException");
e.printStackTrace();
mStarted = false;
initTts();
} catch (NullPointerException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - speak", "NullPointerException");
e.printStackTrace();
mStarted = false;
initTts();
} catch (IllegalStateException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - speak", "IllegalStateException");
e.printStackTrace();
mStarted = false;
initTts();
} finally {
resetCachedParams();
return result;
}
}
}
还有在Activity退出时作一些操作
[java]
@Override
public void onDestroy() {
// Don't forget to shutdown!
if (mTts != null) {
mTts.stop();
mTts.shutdown();
}
super.onDestroy();
}
能看到源码真好...深入学习...呵呵
我们再看下android 到底是怎样stop和shutdown的
[java] view plaincopy
<EMBED id=ZeroClipboardMovie_15 name=ZeroClipboardMovie_15 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=15&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
/**
* Stops speech from the TTS.
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int stop() {
synchronized (mStartLock) {
int result = ERROR;
if (!mStarted) {
return result;
}
try {
result = mITts.stop(mPackageName);
} catch (RemoteException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - stop", "RemoteException");
e.printStackTrace();
mStarted = false;
initTts();
} catch (NullPointerException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - stop", "NullPointerException");
e.printStackTrace();
mStarted = false;
initTts();
} catch (IllegalStateException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - stop", "IllegalStateException");
e.printStackTrace();
mStarted = false;
initTts();
} finally {
return result;
}
}
}
还有shutdown函数:
[java]
/**
* Shuts down the TTS. It is good practice to call this in the onDestroy
* method of the Activity that is using the TTS so that the TTS is stopped
* cleanly.
*/
public void shutdown() {
try {
mContext.unbindService(mServiceConnection);
} catch (IllegalArgumentException e) {
// Do nothing and fail silently since an error here indicates that
// binding never succeeded in the first place.
}
}
还有Activity的destroy函数:
[java]
/**
* Perform any final cleanup before an activity is destroyed. This can
* happen either because the activity is finishing (someone called
* {@link #finish} on it, or because the system is temporarily destroying
* this instance of the activity to save space. You can distinguish
* between these two scenarios with the {@link #isFinishing} method.
*
* <p><em>Note: do not count on this method being called as a place for
* saving data! For example, if an activity is editing data in a content
* provider, those edits should be committed in either {@link #onPause} or
* {@link #onSaveInstanceState}, not here.</em> This method is usually implemented to
* free resources like threads that are associated with an activity, so
* that a destroyed activity does not leave such things around while the
* rest of its application is still running. There are situations where
* the system will simply kill the activity's hosting process without
* calling this method (or any others) in it, so it should not be used to
* do things that are intended to remain around after the process goes
* away.
*
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
* thrown.</em></p>
*
* @see #onPause
* @see #onStop
* @see #finish
* @see #isFinishing
*/
protected void onDestroy() {
mCalled = true;
// dismiss any dialogs we are managing.
if (mManagedDialogs != null) {
final int numDialogs = mManagedDialogs.size();
for (int i = 0; i < numDialogs; i++) {
final Dialog dialog = mManagedDialogs.valueAt(i);
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
// close any cursors we are managing.
int numCursors = mManagedCursors.size();
for (int i = 0; i < numCursors; i++) {
ManagedCursor c = mManagedCursors.get(i);
if (c != null) {
c.mCursor.close();
}
}
}
好了,这个TTS就到这里。
至于现在到底是否支持中文发音这个我还没调查过。实在不行的话我们就做English版的软件也不错,单词发音,语音导航等等都是可以运用TTS的。
还有再唠叨一下,最近居然看到源码了,爽YY呀。感觉这一步就像是从了解一个人的表面到了解其本质...从上到下,从外到内...
来源:oschina
链接:https://my.oschina.net/u/1757911/blog/386423