您的位置:首页 > 移动开发 > Android开发

Android TTS学习——继续爱的表白

2010-08-13 17:33 357 查看
一.
简单介绍

在上一篇里
http://blog.csdn.net/ichliebephone/archive/2010/08/10/5802739.aspx
我们讲到了TTS
最主要的一个API


public
int speak ( String
text, int queueMode,
HashMap < String ,
String > params)

其中我们介绍了前两个参数,第三个参数设置了null
,并没有具体介绍。

而且我们在介绍Android TTS
提供的功能时,说到TTS
提供了两个接口,第一个初始化接口OnInitListener

我们已经使用过了,而第二个接口OnUtteranceCompletedListener

我们还没有使用到。

首先我们就来简单介绍一下这个接口的使用方式。TTS
引擎进行语音合成的每个语音片段叫做"utterance ",
而且在送给speak
函数进行语音合成时,可以为这次的语音片段"utterance "
设置一个ID
。OnUtteranceCompletedListener

这个接口里定义了一个回调函数,当设置了ID
的语音片段"utterance "
语音合成结束后就会调用这个回调函数。然后我们就可以在这回调函数里进行我们需要的操作,比如在某个特定ID
的语音片段结束后播放音乐,或者跟踪记录哪些文本内容已经被朗读等。

下面利用这个接口的功能完成一个Demo
例子,朗读一段爱的表白,并且在程序退出后可以记住这次表白到哪了,下次在她再次打开程序时,就可以继续这爱的表白。

二.

实例分析

我们希望做的效果如下:



图1
实现效果图

在界面上体现不出这个Demo
的特点,除了一长串英文的爱的表白外,还有一个Speak
按钮。但当点击了Speak
按钮开始朗读上面的表白后,在没有读完就退出程序后,下次再启动后还会接着上次的继续朗读。

创建一个Android
工程,工程名为AndroidTTSDemoThird,
其中SDK
必须选择1.6
版本及以上。

其中Main.xml
文件很简单,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<EditText android:id="@+id/inputText"
android:hint="Input the text here!"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</EditText>
<Button android:text="Speak"
android:id="@+id/speakBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:enabled="false"
></Button>

</LinearLayout>


Java
文件的编写:

这次要实现
OnInitListener

OnUtteranceCompletedListener

两个接口

public class AndroidTTSDemoThird extends Activity implements OnInitListener, OnUtteranceCompletedListener{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

@Override
public void onInit(int status) {
// TODO Auto-generated method stub
//TTS Engine初始化完成

}
@Override
public void onUtteranceCompleted(String utteranceId) {
// TODO Auto-generated method stub
//一个语音片段结束后的回调函数

}
}


接着定义好下面要用到的几个变量:

//定义变量
private EditText inputText = null;
private Button speakBtn = null;
private TextToSpeech mTts;
private static final String TAG = "TTS Demo";
private static final String STORE_NAME = "preferenceFile";
private static final String loveConfession = "You complete me. You had me at hello, you had me at hello. To the world you maybe one person, but to one person you maybe the world. Please believe me, I was prepared for everything,except you. I love that you are the last person I want to talk to before I go to sleep at night. Love means never having to say you're sorry. So choose me. Marry me. Let me make you happy. ";
private String[] loveArray;
private int lastUtterance = -1;
private HashMap<String, String> params = new HashMap<String, String>();


因为通过前面的两个
Demo
,我们知道已经安装了
TTS
需要的数据,因此这里我们可以在
onCreate
函数中直接创建一个
TextToSpeech
实例,

//创建TextToSpeech实例,初始化完成后会调用OnInitListener(第二个参数)的回调函数
mTts = new TextToSpeech(this,
this  // TextToSpeech.OnInitListener
);


成功创建一个
TextToSpeech
后,就会调用接口
OnInitListener
中定义的回调函数

@Override
public void onInit(int status) {
// TODO Auto-generated method stub
//TTS Engine初始化完成
if(status == TextToSpeech.SUCCESS)
{
int result = mTts.setLanguage(Locale.US);
//设置发音语言
if(result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED)
//判断语言是否可用
{
Log.v(TAG, "Language is not available");
speakBtn.setEnabled(false);
}
else
{
speakBtn.setEnabled(true);
//设置一个语音片段结束后的回调函数
mTts.setOnUtteranceCompletedListener(this);
}
}
}


和前面的
Demo
相比,这里多了一句
mTts
.setOnUtteranceCompletedListener(
this

);

就是设置语音片段结束后的回调函数。

接着在
onCreate
函数中设置
EditText


Button
的使用:

//设置控件
inputText = (EditText)findViewById(R.id.inputText);
speakBtn = (Button)findViewById(R.id.speakBtn);

inputText.setText(loveConfession);
speakBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
//处理输入框里的内容
StringTokenizer loveTokens = new StringTokenizer(inputText.getText().toString(),",.");
int i = 0;
loveArray = new String[loveTokens.countTokens()];
while(loveTokens.hasMoreTokens())
{
loveArray[i++] = loveTokens.nextToken();
}
//朗读输入框里的内容
speakText();
}
});



SpeakBtn

onClick
事件中,先把输入框中的内容按
','

'.'
分割成一个个短的部分并保存在字符串数组中,然后调用我们写的
speakText()
函数来进行朗读。

speakText()
函数的定义如下:

private void speakText()
{
lastUtterance++;
if(lastUtterance >= loveArray.length)
{
lastUtterance = 0;
}
Log.v(TAG, "the begin utterance is " + lastUtterance);
for(int i = lastUtterance; i < loveArray.length; i++)
{
//为每个语音片段都设置一个标记
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, String.valueOf(i));
mTts.speak(loveArray[i], TextToSpeech.QUEUE_ADD, params);
}
}


lastUtterance
变量保存上一个语音片段的
ID

params

HashMap<String,
String>
类型,键值对形式的变量,在这里我们的键
name

TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID
,是一个
UTTERANCE_ID
,值
value

String.valueOf(i)
,其实只要是任何字符串变量都行,为了方便我们设置的为有顺序的数字。然后把这个键值对变量添加给
speak
函数,
TTS
引擎就会在这个语音片段朗读结束后通知我们,调用设置好的回调函数
onUtteranceCompleted(String
utteranceId)
,这个回调函数的内容如下:

@Override
public void onUtteranceCompleted(String utteranceId) {
// TODO Auto-generated method stub
//一个语音片段结束后的回调函数
Log.v(TAG, "Get completed message for the utteranceId " + utteranceId);
//用lastUtterance记录当前结束的语音片段
lastUtterance = Integer.parseInt(utteranceId);
}


很简单,主要就是把当前刚结束的这个语音片段
ID--utteranceId
保存到
lastUtterance
变量中,这样在程序退出时,我们就可以保存这个变量,

@Override
protected void onDestroy() {
// TODO Auto-generated method stub
//释放TTS的资源
if(mTts != null)
{
mTts.stop();
mTts.shutdown();
}
//保存lastUtterance值
SharedPreferences settings = getSharedPreferences(STORE_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putInt("lastUtterance", lastUtterance);
editor.commit();
Log.v(TAG, "the stored lastUtterance is " + lastUtterance);

super.onDestroy();
}


首先是释放
TTS
资源,然后把
lastUtterance
变量的值以键值对的方式保存在系统中,这样下次启动程序时
lastUtterance
就可以从系统中读取上次退出时保存的值。在
onCreate
函数中添加获取保存的
lastUtterance
代码:

//获得保存的lastUtterance值
SharedPreferences settings = getSharedPreferences(STORE_NAME, 0);
lastUtterance = settings.getInt("lastUtterance", -1);
Log.v(TAG, "the restored lastUtterance is " + lastUtterance);


至此,这个
Demo
完成了,运行后点击
Speak
按钮会朗读文本框中的经典的爱的表白,一小段一小段朗读,每朗读完一小段程序都会调用回调函数
onUtteranceCompleted
记录刚朗读完的那个小段的
ID
,当所有的表白没朗读完就按返回退出程序时,程序在
onDestroy()
里把记录着的片段
ID
保存在系统中,这样下次再次打开程序时就可以接着上次继续这爱的表白。

注:文章参加“
首届Google暑期大学生博客分享大赛——2010 Andriod篇”
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: