This tutorial will teach you to give your applications a voice with the Android SDK text to speech engine!
The
Android text to speech engine still seems to be a pretty underused
resource in Android apps. However, implementing it in your own
applications is straightforward. There are a few potential issues and
choices you need to consider, but for most purposes, the process is not a
complex one. In this tutorial we jump around a bit within one Android
Activity, but don’t worry, the complete code is listed at the end. The
aim is to give you a clear idea of the what’s going on at each
processing stage so that you can successfully use the function in any
app.
Step 1: Start or Open an Android Project
If
you already have an application you want to implement Text To Speech
with, open it in your IDE. Otherwise, create a new Android project. You
can use the code in this tutorial with any Activity class. For
demonstration, we will first create some user interface elements. Again,
if you already have your own UI, you can use it instead.
Step 2: Create User Interface Elements
Add
some user interface elements to your application, allowing the user to
enter text and initiate speech playback using a button. In the XML
layout file for your Activity, which will be “main.xml” if you created a
new project, add the following markup:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
< TextView android:id = "@+id/intro"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:text = "Enter some text:"
/>
< EditText android:id = "@+id/enter"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
/>
< Button android:id = "@+id/speak"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "Speak"
/>
|
Your
XML layout files should be in the “res/layout” directory within your
application package. This code adds three user interface elements: a
label with some instructional text in it, an editable text-field, and a
button. The user will be able to enter text into the field, then press
the button to hear it spoken. If you are using an existing project, you
can of course use the interface elements you already have. If you are
using these new elements, you can alter them to suit the design of your
own app.
Step 3: Listen For User Events
Open
the Java file for the Activity you want to implement TTS in. If you
created a new app, open the main class file. In Eclipse, your Activity
should automatically have the “onCreate” method within it and should
extend “Activity” as part of its declaration. At the top of the class
file, add the following import statements so that your app can listen
for button clicks:
1
2
3
|
import android.view.View.OnClickListener;
import android.widget.Button;
import android.view.View;
|
Alter the class declaration to implement the “OnClickListener” interface, as in the following sample line of code:
1
|
public class SpeakingAndroid extends Activity implements OnClickListener
|
Alter
the class name to suit your own application details. Your IDE may
display warnings because your class has not yet implemented
“OnClickListener” correctly – just ignore these for now. In the
“onCreate” method, add the following code:
1
2
|
Button speakButton = (Button)findViewById(R.id.speak);
speakButton.setOnClickListener( this );
|
If
you did not add the button using “speak” as its ID in your XML layout
file, alter this code to reflect the correct ID value. This sets your
Activity class up to handle user button clicks. Add the following method
outline to your class:
1
2
3
|
public void onClick(View v) {
}
|
Inside this method you will begin the Text To Speech functionality.
Step 4: Get the Entered Text
When
the user clicks the button, your app needs to get any text entered so
that you can pass it to the TTS method. Add the following import
statement at the top of your class declaration so that your code can
refer to the editable text-field:
1
|
import android.widget.EditText;
|
Inside your “onClick” method, add the following code:
1
2
|
EditText enteredText = (EditText)findViewById(R.id.enter);
String words = enteredText.getText().toString();
|
This
code first acquires a reference to the text-field using its ID value,
so alter this if you used a different value in your layout XML. Next,
the code gets the text from the field and stores it as a string
variable. If the user has not entered any text this will be empty.
Depending on the logic within your application you may wish to add a
conditional test, checking that the string is not null or zero in
length, but this is not generally necessary.
Step 5: Create a Speech Method
To
keep your Android classes well-organized, it’s advisable to create
dedicated methods for processes you may want to use more than once. Add
the following method outline to your Activity:
1
2
3
|
private void speakWords(String speech) {
}
|
This
is where your TTS processing will go. Back in the “onClick” listener
method, call this new method, passing it the string variable your code
copied from the text-field:
Using a method for the TTS process means that your code can call on it elsewhere if necessary.
Step 6: Implement TTS Within the Class
To
utilize the TTS facility, you need to make a few more changes to your
class declaration. Add the following import statements for the TTS
classes at the top of your file:
1
2
|
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
|
You
also need to implement one more interface, so alter your class
declaration outline to add “OnInitListener” as in the following example:
1
|
public class SpeakingAndroid extends Activity implements OnClickListener, OnInitListener
|
Remember
to use your own class name. Again, your IDE will alert you to the fact
that you haven’t yet implemented this interface but don’t worry, you
will soon.
Step 7: Check for TTS Data
Your
app needs to check that the user has the data necessary for the TTS
function before you call its methods. Declare and instantiate the
following instance variable at the top of your Activity class
declaration, before the “onCreate” method:
1
|
private int MY_DATA_CHECK_CODE = 0 ;
|
Add the following import statement at the top of the class:
1
|
import android.content.Intent;
|
In the “onCreate” method, add the following:
1
2
3
|
Intent checkTTSIntent = new Intent();
checkTTSIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkTTSIntent, MY_DATA_CHECK_CODE);
|
This
code creates a new Intent purely for the purposes of checking the user
data. When the checking process is complete, the code will call the
“onActivityResult” method.
Step 8: Create a TTS Instance
Declare an instance variable for your TTS object at the top of the class declaration, also before the “onCreate” method:
1
|
private TextToSpeech myTTS;
|
Add the “onActivityResult” to your class as follows:
1
2
3
4
5
6
7
8
9
10
11
12
|
protected void onActivityResult( int requestCode, int resultCode, Intent data) {
if (requestCode == MY_DATA_CHECK_CODE) {
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
myTTS = new TextToSpeech( this , this );
}
else {
Intent installTTSIntent = new Intent();
installTTSIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installTTSIntent);
}
}
}
|
When
the data checking Intent completes, the app calls this method, passing
it the “MY_DATA_CHECK_CODE” variable indicating whether or not the user
has the TTS data installed. If the data is present, the code goes ahead
and creates an instance of the TTS class. If the data is not present,
the app will prompt the user to install it.
Step 9: Provide the onInit Method
Your
class declaration is implementing “OnInitListener” so you must provide
an “onInit” method. In this method, you can carry out any final set-up
checks you need, as well as choosing settings for your TTS instance,
such as language and locale options. Add the following import statement
at the top of your class:
Add the “onInit” method to the class as follows:
1
2
3
4
5
|
public void onInit( int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
myTTS.setLanguage(Locale.US);
}
}
|
This
code checks that the TTS resource is successfully instantiated, then
sets a US English Locale for the speech operations. You can optionally
output an error message for users if the TTS does not successfully
instantiate by adding the following after the “if” block:
1
2
3
|
else if (initStatus == TextToSpeech.ERROR) {
Toast.makeText( this , "Sorry! Text To Speech failed..." , Toast.LENGTH_LONG).show();
}
|
If you use this code you will also need to import the Toast class by adding the following statement at the top of your file:
1
|
import android.widget.Toast;
|
Your
app can carry out checks on the user device, such as available
languages, as in the following extended version of the statement
creating the TTS object inside the first conditional statement:
1
|
if (myTTS.isLanguageAvailable(Locale.US)==TextToSpeech.LANG_AVAILABLE) myTTS.setLanguage(Locale.US);
|
Step 10: Speak!
Finally, your app is ready to speak. Inside the “speakWords” method, add the following code:
1
|
myTTS.speak(speech, TextToSpeech.QUEUE_FLUSH, null );
|
There
are lots of options here in terms of how your app handles speech. This
code instructs the app to speak the text string immediately. If you want
to add consecutive speech operations, you can instruct the app to wait
until any current speech operations finish by adding your new speech
item to a queue, as follows:
1
|
myTTS.speak(speech, TextToSpeech.QUEUE_ADD, null );
|
Once your class is finished with the TTS, you can optionally shut it down as follows:
Don’t include this line if you want your users to be able to make the app speak more than once.
Conclusion
To see how all of these elements fit together, here is the complete class declaration:
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
|
import android.app.Activity;
import android.os.Bundle;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.view.View;
import android.widget.EditText;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.content.Intent;
import java.util.Locale;
import android.widget.Toast;
public class SpeakingAndroid extends Activity implements OnClickListener, OnInitListener {
private TextToSpeech myTTS;
private int MY_DATA_CHECK_CODE = 0 ;
public void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.main);
Button speakButton = (Button)findViewById(R.id.speak);
speakButton.setOnClickListener( this );
Intent checkTTSIntent = new Intent();
checkTTSIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkTTSIntent, MY_DATA_CHECK_CODE);
}
public void onClick(View v) {
EditText enteredText = (EditText)findViewById(R.id.enter);
String words = enteredText.getText().toString();
speakWords(words);
}
private void speakWords(String speech) {
myTTS.speak(speech, TextToSpeech.QUEUE_FLUSH, null );
}
protected void onActivityResult( int requestCode, int resultCode, Intent data) {
if (requestCode == MY_DATA_CHECK_CODE) {
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
myTTS = new TextToSpeech( this , this );
}
else {
Intent installTTSIntent = new Intent();
installTTSIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installTTSIntent);
}
}
}
public void onInit( int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
if (myTTS.isLanguageAvailable(Locale.US)==TextToSpeech.LANG_AVAILABLE)
myTTS.setLanguage(Locale.US);
}
else if (initStatus == TextToSpeech.ERROR) {
Toast.makeText( this , "Sorry! Text To Speech failed..." , Toast.LENGTH_LONG).show();
}
}
}
|
Remember
to use your own class name and to indicate your application package at
the top of the file. If you are using Eclipse, you should not need to
add all of the import statements manually, as the IDE will insert some
of them automatically. Run your app in the Android emulator and hear it
in action.
This is a basic overview of implementing Text To Speech
in your Android apps. The TTS resource provides a wide range of
additional options you may want to explore depending on the nature of
your apps. When calling the TextToSpeech object “speak” method for
example, you can pass a HashMap object indicating the details of more
complex playback options.