当前位置: 代码迷 >> Android >> Android TTS学习——持续爱的表白(转)
  详细解决方案

Android TTS学习——持续爱的表白(转)

热度:36   发布时间:2016-05-01 17:29:17.0
Android TTS学习——继续爱的表白(转)

?

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

分类:?Android TTS?Google Android?2561人阅读?评论(1)?收藏?举报

一.?简单介绍

在上一篇里

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?文件很简单,如下所示:

?

[xhtml]?view plaincopy
  1. <?xml?version="1.0"?encoding="utf-8"?>??
  2. <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
  3. ????android:orientation="vertical"??
  4. ????android:layout_width="fill_parent"??
  5. ????android:layout_height="fill_parent"??
  6. ????>??
  7. ????<EditText?android:id="@+id/inputText"???
  8. ????????????????android:hint="Input?the?text?here!"???
  9. ????????????????android:layout_width="fill_parent"???
  10. ????????????????android:layout_height="wrap_content">??
  11. ????????????????</EditText>??
  12. ????<Button?android:text="Speak"???
  13. ????????????????android:id="@+id/speakBtn"???
  14. ????????????????android:layout_width="wrap_content"???
  15. ????????????????android:layout_height="wrap_content"??
  16. ????????????????android:layout_gravity="center_horizontal"??
  17. ????????????????android:enabled="false"??
  18. ????????????????></Button>??
  19. ??????????????????
  20. </LinearLayout>??

?

?

Java?文件的编写:

这次要实现?OnInitListener??OnUtteranceCompletedListener?两个接口

?

[java]?view plaincopy
  1. public?class?AndroidTTSDemoThird?extends?Activity?implements?OnInitListener,?OnUtteranceCompletedListener{??
  2. ????/**?Called?when?the?activity?is?first?created.?*/??
  3. ????@Override??
  4. ????public?void?onCreate(Bundle?savedInstanceState)?{??
  5. ????????super.onCreate(savedInstanceState);??
  6. ????????setContentView(R.layout.main);??
  7. ????}??
  8. ??????
  9. ????@Override??
  10. ????public?void?onInit(int?status)?{??
  11. ????????//?TODO?Auto-generated?method?stub??
  12. ????????//TTS?Engine初始化完成??
  13. ??????????
  14. ????}??
  15. ????@Override??
  16. ????public?void?onUtteranceCompleted(String?utteranceId)?{??
  17. ????????//?TODO?Auto-generated?method?stub??
  18. ????????//一个语音片段结束后的回调函数??
  19. ??????????
  20. ????}??
  21. }??

?

?

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

?

[java]?view plaincopy
  1. //定义变量??
  2. ????private?EditText?inputText?=?null;??
  3. ????private?Button?speakBtn?=?null;??
  4. ????private?TextToSpeech?mTts;??
  5. ????private?static?final?String?TAG?=?"TTS?Demo";??
  6. ????private?static?final?String?STORE_NAME?=?"preferenceFile";??
  7. ????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.?";??
  8. ????private?String[]?loveArray;???
  9. ????private?int?lastUtterance?=?-1;??
  10. ????private?HashMap<String,?String>?params?=?new?HashMap<String,?String>();??

?

?

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

?

[java]?view plaincopy
  1. //创建TextToSpeech实例,初始化完成后会调用OnInitListener(第二个参数)的回调函数??
  2. mTts?=?new?TextToSpeech(this,??
  3. ????????this??//?TextToSpeech.OnInitListener??
  4. ????????);??

?

?

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

?

[java]?view plaincopy
  1. @Override??
  2. public?void?onInit(int?status)?{??
  3. ????//?TODO?Auto-generated?method?stub??
  4. ????//TTS?Engine初始化完成??
  5. ????if(status?==?TextToSpeech.SUCCESS)??
  6. ????{??
  7. ????????int?result?=?mTts.setLanguage(Locale.US);??
  8. ????????//设置发音语言??
  9. ????????if(result?==?TextToSpeech.LANG_MISSING_DATA?||?result?==?TextToSpeech.LANG_NOT_SUPPORTED)??
  10. ????????//判断语言是否可用??
  11. ????????{??
  12. ????????????Log.v(TAG,?"Language?is?not?available");??
  13. ????????????speakBtn.setEnabled(false);??
  14. ????????}??
  15. ????????else??
  16. ????????{??
  17. ????????????speakBtn.setEnabled(true);??
  18. ????????????//设置一个语音片段结束后的回调函数??
  19. ????????????mTts.setOnUtteranceCompletedListener(this);??
  20. ????????}??
  21. ????}?????
  22. }??

?

?

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

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

?

接着在?onCreate?函数中设置?EditText??Button?的使用:

?

[java]?view plaincopy
  1. ??????//设置控件??
  2. ??????inputText?=?(EditText)findViewById(R.id.inputText);??
  3. ??????speakBtn?=?(Button)findViewById(R.id.speakBtn);??
  4. ???????
  5. ???inputText.setText(loveConfession);????
  6. ??????speakBtn.setOnClickListener(new?OnClickListener()?{?????????
  7. ????public?void?onClick(View?v)?{??
  8. ????????//?TODO?Auto-generated?method?stub??
  9. ????????//处理输入框里的内容??
  10. ????????StringTokenizer?loveTokens?=?new?StringTokenizer(inputText.getText().toString(),",.");??
  11. ????????int?i?=?0;??
  12. ????????loveArray?=?new?String[loveTokens.countTokens()];??
  13. ????????while(loveTokens.hasMoreTokens())??
  14. ????????{??
  15. ????????????loveArray[i++]?=?loveTokens.nextToken();??
  16. ????????}??
  17. ????????//朗读输入框里的内容??
  18. ????????speakText();??
  19. ????}??
  20. });??

?

?

?SpeakBtn??onClick?事件中,先把输入框中的内容按?','??'.'?分割成一个个短的部分并保存在字符串数组中,然后调用我们写的?speakText()?函数来进行朗读。

speakText()?函数的定义如下:

?

[java]?view plaincopy
  1. private?void?speakText()??
  2. {??
  3. ????lastUtterance++;??
  4. ????if(lastUtterance?>=?loveArray.length)??
  5. ????{??
  6. ????????lastUtterance?=?0;??
  7. ????}??
  8. ????Log.v(TAG,?"the?begin?utterance?is?"?+?lastUtterance);??
  9. ????for(int?i?=?lastUtterance;?i?<?loveArray.length;?i++)??
  10. ????{??
  11. ????????//为每个语音片段都设置一个标记??
  12. ????????params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,?String.valueOf(i));??
  13. ????????mTts.speak(loveArray[i],?TextToSpeech.QUEUE_ADD,?params);??
  14. ????}??
  15. }??

?

?

lastUtterance?变量保存上一个语音片段的?ID??params??HashMap<String, String>?类型,键值对形式的变量,在这里我们的键?name??TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,是一个?UTTERANCE_ID?,值?value??String.valueOf(i)?,其实只要是任何字符串变量都行,为了方便我们设置的为有顺序的数字。然后把这个键值对变量添加给?speak?函数,?TTS?引擎就会在这个语音片段朗读结束后通知我们,调用设置好的回调函数?onUtteranceCompleted(String utteranceId)?,这个回调函数的内容如下:

?

[java]?view plaincopy
  1. @Override??
  2. public?void?onUtteranceCompleted(String?utteranceId)?{??
  3. ????//?TODO?Auto-generated?method?stub??
  4. ????//一个语音片段结束后的回调函数??
  5. ????Log.v(TAG,?"Get?completed?message?for?the?utteranceId?"?+?utteranceId);??
  6. ????//用lastUtterance记录当前结束的语音片段??
  7. ????lastUtterance?=?Integer.parseInt(utteranceId);??
  8. }??

?

?

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

?

[java]?view plaincopy
  1. @Override??
  2. protected?void?onDestroy()?{??
  3. ????//?TODO?Auto-generated?method?stub??
  4. ????//释放TTS的资源??
  5. ????if(mTts?!=?null)??
  6. ????{??
  7. ????????mTts.stop();??
  8. ????????mTts.shutdown();??
  9. ????}??
  10. ????//保存lastUtterance值??
  11. ????SharedPreferences?settings?=?getSharedPreferences(STORE_NAME,?0);??
  12. ????SharedPreferences.Editor?editor?=?settings.edit();??
  13. ????editor.putInt("lastUtterance",?lastUtterance);??
  14. ????editor.commit();??
  15. ????Log.v(TAG,?"the?stored?lastUtterance?is?"?+?lastUtterance);??
  16. ??????
  17. ????super.onDestroy();??
  18. }??

?

?

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

?

[java]?view plaincopy
  1. //获得保存的lastUtterance值??
  2. SharedPreferences?settings?=?getSharedPreferences(STORE_NAME,?0);??
  3. lastUtterance?=?settings.getInt("lastUtterance",?-1);??
  4. Log.v(TAG,?"the?restored?lastUtterance?is?"?+?lastUtterance);??

?

?

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

?

注:文章参加“?首届Google暑期大学生博客分享大赛——2010 Andriod篇

  相关解决方案