本文主要演示如何使用Android系统中的 Text-to-speech API实现将指定的文本转成不同语言音频输出,以增强用户体验。
侦测TTS资源的可用性
当前大部分加载有Android操作系统的设备都通过这套引擎来提供TTS功能,但由于一些设备的存储空间非常有限而影响到TTS无法最大限度的发挥功能,因此,建议首先使用检测模块,让用户自行选择是否有足够的空间或者需求来加载此项资源。 相关的代码如下:
1 2 3
| Intent checkIntent = new Intent(); checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA); startActivityForResult(checkIntent, RESULT_CHECK_TEXT_2_SPEECH);
|
从以上代码可以看出,检测是通过Intent来调用TextToSpeech引擎提供的功能来实现的,因此需要在对应Activity的返回方法中获取检测的结果,代码如下:
1 2 3 4 5 6 7 8 9
| if (requestCode == RESULT_CHECK_TEXT_2_SPEECH) { if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) { Log.d(Constants.TAG, "support tts"); } else { Intent installIntent = new Intent(); installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA); startActivity(installIntent); } }
|
当返回的代码是: TextToSpeech.Engine.CHECK_VOICE_DATA_PASS, 说明该设备已经具备了使用TTS的相关资源。否则,调用 ACTION_INSTALL_TTS_DATA Action来安装相关资源。
初始化
如果资源允许,就可以初始化 TTS 引擎中的 Text-To-Speech 对象来进行相关的操作了。
初始化并设置语言为英语:
1 2 3 4 5 6 7 8
| textToSpeech = new TextToSpeech(MainActivity.this, new TextToSpeech.OnInitListener() { @Override public void onInit(int status) { if (status == TextToSpeech.SUCCESS) { textToSpeech.setLanguage(Locale.ENGLISH); } } });
|
朗读文本
1
| textToSpeech.speak("Hello World", TextToSpeech.QUEUE_FLUSH, null);
|
完整的示例代码
在示例代码中,我们在一个Activity中建立了两个按钮,一个按钮执行资源检测的动作,一个用来朗读内容”hello world”的文本。学员可以很方便的扩展这个示例代码来实现自己的需求。
Activity 的 Java 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| package cn.com.hohistar.tutorial.text2speech;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent; import android.os.Bundle; import android.speech.tts.TextToSpeech; import android.util.Log;
import java.util.Locale;
import butterknife.ButterKnife; import butterknife.OnClick; import cn.com.hohistar.tutorial.text2speech.common.Constants;
public class MainActivity extends AppCompatActivity {
private static final int RESULT_CHECK_TEXT_2_SPEECH = 100;
private TextToSpeech textToSpeech;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
ButterKnife.bind(this);
textToSpeech = new TextToSpeech(MainActivity.this, new TextToSpeech.OnInitListener() {
@Override public void onInit(int status) { Log.e(Constants.TAG, "Result of init Text2Speech:" + status); if (status == TextToSpeech.SUCCESS) { textToSpeech.setLanguage(Locale.ENGLISH); } } }); }
@OnClick(R.id.btnCheck) void onCheck() { Log.d(Constants.TAG, "onCheck"); Intent checkIntent = new Intent(); checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA); startActivityForResult(checkIntent, RESULT_CHECK_TEXT_2_SPEECH); }
@OnClick(R.id.btnRead) void onRead() { textToSpeech.speak("Hello World", TextToSpeech.QUEUE_FLUSH, null); }
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == RESULT_CHECK_TEXT_2_SPEECH) { if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) { Log.d(Constants.TAG, "support tts"); } else { Intent installIntent = new Intent(); installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA); startActivity(installIntent); } } }
@Override protected void onDestroy() { if (textToSpeech != null) { textToSpeech.stop(); textToSpeech.shutdown(); textToSpeech = null; } super.onDestroy(); }
}
|
Activity 的界面定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
<Button android:id="@+id/btnCheck" android:layout_width="88dp" android:layout_height="0dp" android:layout_marginTop="120dp" android:text="Check" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
<Button android:id="@+id/btnRead" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="65dp" android:text="Read" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/btnCheck" /> </androidx.constraintlayout.widget.ConstraintLayout>
|