Use Text-to-Speech on Android to Read Out Incoming Messages

Apps with interfaces that make use of voice have a unique appeal. They tend to make their users feel that they are using something futuristic. Since its early days, Android has had very robust text-to-speech (TTS) functionality. This year, Google has added a lot of high-quality voices to its TTS engine and that's all the more reason for developers to use it in their apps.

In this tutorial, you'll learn how to create a simple app—with a minimalist user interface—that can receive text messages and read them to the user.

Prerequisites

Ensure that you have the Eclipse ADT Bundle set up. You can download it at the Android Developer website. For best results, you are also going to need a real Android device and some friends who can send you text messages.

1. Create a New Project

Start Eclipse, and create a new Android application. Call this application SMSReader. If you think you are going to publish this app to Google Play to share it with your friends, then make sure you use a unique package name. Set the Minimum Required SDK to Android 2.2 and set the Target SDK to Android 4.4.

New Android Application window

This app will have one Activity. Select Create Activity and choose Empty Activity.

Create an Empty new Activity

Name it MainActivity and click Finish.

Name the Activity

2. Edit the Manifest

This app needs three permissions:

  • RECEIVE_SMS to know that the device has received an SMS
  • READ_SMS to read that SMS
  • READ_CONTACTS to map the phone number of the sender to a name (if possible)

Add the following lines to your AndroidManifest.xml.

This app is going to have only one screen orientation, portrait. Therefore, edit the activity tag and add the following attribute to it:

The manifest is now complete.

3. Edit strings.xml

It is not absolutely necessary, but storing all strings that the application uses in the res/values/strings.xml file is a good practice. Edit this file so that it has the following contents:

Most of these strings are used in the next step.

4. Edit the Layout

Edit res/layout/activity_main.xml to add the following:

  • TextView to display the name of the person who sent the latest SMS
  • TextView to display the contents of the latest SMS
  • ToggleButton to toggle speech output on and off

After adding code for positioning and styling these elements, your file should have the following contents:

The layout for our application is now complete.

5. Create a Helper Class

We're now going to create a helper class for the TTS engine. Create a new Java class and call it Speaker.java. This class is used to avoid calling the TTS API directly from the Activity.

This class implements the OnInitListener interface so that it knows when the TTS engine is ready. We store this ready state in a boolean variable named ready. We use another boolean variable named allowed whose value is true only if the user has allowed the TTS engine to speak. We also add methods to get and set the value of this variable. At this point, Speaker.java should have the following contents:

The OnInitListener interface has only one method, onInit. This method is called when the TTS engine has been initialized. The status parameter lets us know if the initialization was successful. Once we know that the initialization was successful, we set the language of the TTS engine. This is important to produce speech that is comprehensible. Add the following code:

Next, we add a method named speak, which uses the engine to read out any text that is passed to it. Before doing so, it checks if both the allowed and the ready values are true. The speech it generates is placed in the notification stream.

We then add a method that plays silence for a specified duration. Using this method, we can add pauses to the speech to make it sound a little clearer. Add the following code to the implementation:

Finally, add a method to free up resources when the TTS engine is no longer needed.

6. Edit the Activity Class

Edit MainActivity.java and declare all the views that we mentioned in the layout. Declare two integers, LONG_DURATION and SHORT_DURATION. These are merely values that are passed to the Speaker's pause method.

Also declare a CHECK_CODE integer. It's value isn't important. It is passed to the startActivityforResult method and then used to identify the result.

Lastly, declare a Speaker object and a BroadcastReceiver object.

At this point, your class should look like this:

Add a method to check if a TTS engine is installed on the device. The check is performed by making use of the result of another Activity.

When the result of startActivityForResult arrives, the onActivityResult method is called. Therefore, we need to override it. In this method, if the result is positive, we initialize the Speaker object. If no TTS engine is installed, we redirect the user to install it.

It is now time to create our BroadcastReceiver to deal with the messages that the device is receiving. Whenever there are new messages, its onReceive method is called. We parse the messages, which arrive as byte arrays, using the SmsMessage class. Once the message is parsed, we use methods like getDisplayMessageBody and getOriginatingAddress to extract meaningful information out of it.

With this information, we generate the text that the TTS engine should read out. We pause for LONG_DURATION before reading out a new SMS and for SHORT_DURATION between the utterances of the SMS sender's name and the SMS's body.

Add the following code to the implementation:

We can only extract the phone number of the sender from the message. To map this number to a contact's name, we have to make use of the user's contacts. The following method queries the contacts data. If the phone number is not available in the user's contacts, then it simply returns the string unknown number:

Before the BroadcastReceiver can be used, it has to be registered. In the following method, we create an IntentFilter for incoming text messages and then register our smsReceiver for it:

Next, we create the onCreate method. Here's where we initialize all the objects we declared. We initialize the toggleListener to set the value of allowed in the Speaker class.

After these initializations, we call the checkTTS, initializeSMSReceiver, and registerSMSReceiver methods.

Finally, in the onDestroy method of the activity, we unregister our receiver and shut down the TTS engine to free up resources.

7. Run and Test

The app is now ready to be tested. Compile and run it on a physical Android device. Tap the toggle button to enable voice and send yourself an SMS from another phone or ask one of your friends to do so. You should soon be able to hear your phone read out the SMS for you.

Here is a sample of the speech generated by the TTS engine:

Conclusion

In this tutorial, you have learnt to not only use the text-to-speech API, but also to use broadcast receivers and to make sense out of raw SMS data. You can now go on to further customize this app to you needs.

Tags:

Comments

Related Articles