TTS全称为“TextToSpeech”,是Android原生在文本转语音服务。本文将从TTS使用过程,对TTS源码进行分析。

主要涉及的源码有:

framework\base\core\java\android\speech\tts\TextToSpeech.java

framework\base/core\java/android\speech\tts\TextToSpeechService.java

external\svox\pico\src\com\svox\pico\PicoService.java

external\svox\pico\compat\src\com\android\tts\compat\CompatTtsService.java

external\svox\pico\compat\src\com\android\tts\compat\SynthProxy.java

external\svox\pico\compat\jni\com_android_tts_compat_SynthProxy.cpp

external\svox\pico\tts\com_svox_picottsengine.cpp

1、TTS初始化

首先来看TextToSpeech的构造函数

TTS源码解析_第1张图片

紧接着执行initTts操作,初始化TTS:


TTS源码解析_第2张图片

首先连接到用户请求的tts引擎服务,接着是默认引擎,最后是高性能引擎,从代码可以看出高性能引擎优先级最高,默认引擎其次。连接代码如下:

TTS源码解析_第3张图片


Engine.INTENT_ACTION_TTS_SERVICE的值为"android.intent.action.TTS_SERVICE";其连接到的服务为action为"android.intent.action.TTS_SERVICE"的服务,在external\svox\pico目录中的AndroidManifest.xml文件可以发现:

TTS源码解析_第4张图片

所以可以得到这里连接到的服务就是PicoService,其具体代码如下:其继承于CompatTtsService。


TTS源码解析_第5张图片

我们再来看看CompatTtsService这个类,这个类为抽象类,它的父类为TextToSpeechService,其有一个成员SynthProxy类,该类负责调用TTS的C++层代码。

TTS源码解析_第6张图片


我们来看看CompatTtsService的onCreate()方法,该方法中主要对SynthProxy进行了初始化

TTS源码解析_第7张图片


我们紧接着看看SynthProxy的构造函数都干了什么,我也不知道干了什么,但是里面有个静态代码块,其加载了ttscompat动态库,所以它肯定只是一个代理,实际功能由C++本地方法实现

TTS源码解析_第8张图片

在构造函数中,调用了native_setup方法来初始化引擎,其实现在C++层(com_android_tts_compat_SynthProxy.cpp)。代码如下:

TTS源码解析_第9张图片

上面红线init方法在com_svox_picottsengine.cpp中:


TTS源码解析_第10张图片

至此,TTS引擎的初始化就完成了,接下来分析TTS的调用。

2、TTS的调用

我们在应用层一般调用TextToSpeech中的speak()方法,我们来看看其执行流程:


TTS源码解析_第11张图片

接着调用runAction():

TTS源码解析_第12张图片

然后调用mServiceConnection中的runAction方法,其具体代码如下:


TTS源码解析_第13张图片

可以发现最后会回调action.run(mService)方法。接着执行service.playAudio();这里的service为PicoService,其继承于抽象类CompatTtsService,而CompatTtsService继承于抽象类TextToSpeechService.所以会执行TextToSpeechService中的playAudio(),该方法位于TextToSpeechService中mBinder中。该方法如下:

TTS源码解析_第14张图片


接着执行mSynthHandler.enqueueSpeechItem(queueMode, item),其代码如下:

TTS源码解析_第15张图片


我们主要看speechItem.play()该方法在Speechitem类中,其为TextToSpeechService内部类

TTS源码解析_第16张图片


在TextToSpeechService中的playAudio()中代码可以知道这里的speechitem为SynthesisSpeechItemV1。因此在play中执行的playimpl()方法为SynthesisSpeechItemV1类中的playimpl()方法,其代码如下:


TTS源码解析_第17张图片

在playImpl方法中会执行onSynthesizeText方法,这是个抽象方法,记住其传递了一个synthesisCallback,后面会讲到。哪该方法具体实现是在哪里呢,没错,就是在TextToSpeechService的子类CompatTtsService中。来看看它怎么实现的:

TTS源码解析_第18张图片

mNativeSynth为SynthProxy的一个对象,之前说了他是一个代理类,他的speak方法如下:



看到没?什么都没做,就是调用native_speak方法,看它的名字就知道是一个本地方法,那么该方法又是在哪实现呢?就是在com_android_tts_compat_SynthProxy.cpp中,该文件中有下面的映射数组(只截取了一部分):

TTS源码解析_第19张图片

java中对应的native_speak方法对应的C++层代码方法为com_android_tts_compat_SynthProxy_speak方法,接下来来看看该方法是怎么实现的:


TTS源码解析_第20张图片

该方法中调用了TTS引擎中的synthesizeText方法,那么该方法是怎么实现的呢?该方法位于com_svox_picottsengine.cpp中,主要代码(代码太长,只贴部分)如下:



TTS源码解析_第21张图片

其中picoSynthDoneCBPtr()为回调函数,其为TTS初始化过程传入的:


TTS源码解析_第22张图片

而TTS的init初始化在native_setup中被调用


TTS源码解析_第23张图片

那么__ttsSynthDoneCB又是什么呢?其实现如下:


TTS源码解析_第24张图片

callRequestAudioAvailable()方法如下:


TTS源码解析_第25张图片

这个地方调用env->CallIntMethod()方法,在C++层调用java方法,那么这个方法在哪呢?这里的env就是之前说的synthesisCallback,synthesisCallback为PlaybackSynthesisCallback类的对象,那么将会执行PlaybackSynthesisCallback中的audioAvailable()

TTS源码解析_第26张图片

至此,TTS的调用就结束了。


更多相关文章

  1. android 动态向Gallery中添加图片及倒影&&3D效果
  2. Android图片堆叠效果实现
  3. android TextView和EditText中显示图片
  4. Android打鸡蛋游戏源码
  5. location of the android sdk has not been setup in the prefer
  6. Android系统启动流程(源码分析)
  7. wm命令使用方法(修改android 分辨率)修改
  8. Android Studio调错误方法

随机推荐

  1. Android----xml文件中的控件的id设置
  2. Android(安卓)开发中重力感应的实例
  3. android库工程jar打包和混淆
  4. 【小王的安卓之路】Android原生网络请求
  5. Android(安卓)仿当乐游戏详情页面(二)
  6. 包括后台的Android美食APP项目开源代码,an
  7. android权限申请库解析
  8. 成佩涛编程之路——Android控件动画效果(
  9. Android(安卓)开发GPS定位、网络定位、卡
  10. Android支付宝支付接入(支付宝支付SDKV2.0