Академический Документы
Профессиональный Документы
Культура Документы
Now that our prototype can handle different presets, we should provide a fast way to
change, create, or edit user presets through voice recognition. One of the easiest ways to
manage voice recognition is to use Android's Intent messaging object to delegate this
action to another application component. As we discussed at the beginning of the chapter, if
we install and configure a compliant voice input application, Android can use it for voice
recognition.
The main goal is to provide an abstract class that will be extended by our activities in order
to manage recognition callback, while avoiding code repetition. The overall design is as
follows:
We should provide a common interface for activities that need voice recognition.
Note
Job delegation is one of the most useful features of the Android operating system. If
you need more information about how it works under the hood, take a look at the
Android official documentation at
http://developer.android.com/guide/components/intents-filters.html.
The preceding abstraction to reuse voice recognition capability can be achieved with the
following steps:
1. Add in the IRecognitionListener interface in the chronotherm package that
defines the onRecognitionDone() callback used to send back the result to the
caller activity. We can achieve this with the following code:
2. public interface IRecognitionListener {
3.
void onRecognitionDone(int requestCode, String bestMatch);
}
4. Create a new package called voice and add a new abstract class called
RecognizerActivity. This class should be defined as follows:
5. public abstract class RecognizerActivity extends ActionBarActivity
implements IRecognitionListener {
6. Add a public method to initialize the recognition phase, delegating the responsibility
for retrieving the results, with the following code:
7. public void startRecognition(String what, int requestCode) {
8.
Intent intent = new
Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
9.
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US");
10.
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, what);
11.
startActivityForResult(intent, requestCode);
}
The requestCode parameter is the recognition Intent identifier and is used by the
caller activity to properly identify the result and how to handle it. The what
parameter is used to provide an on-screen message if the external application
supports it.
12. Add the onActivityResult() callback to extract the best result and pass it to the
caller activity through the common interface:
13. @Override
14. protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
15.
if (resultCode == RESULT_OK) {
16.
ArrayList<String> matches =
data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
17.
this.onRecognitionDone(requestCode, matches.get(0));
18.
}
}
4. Declare the intent request code that we will use to identify and handle the
recognized result. At the top of the class, add the highlighted code:
9. At the bottom of the onCreate() callback, add the following code to start voice
recognition as soon as possible:
10. mBars = TemperatureWidget.addTo(this, container, true);
11. startRecognition("Choose the preset you want to edit",
VOICE_SETTINGS);
To achieve the preceding interaction flow, proceed with the following steps:
1. As we did for the Settings activity, extend the RecognizerActivity class from
the Overview class, in line with the following snippet:
2. public class Overview extends RecognizerActivity implements
OnDataChangeListener {
3.
//...
}
4. Declare the intent request code that we will use to identify and handle the
recognized result. At the top of the class, add the highlighted code:
5. public class Overview extends RecognizerActivity implements
OnDataChangeListener {
6.
public static final int VOICE_PRESET = 1000;
7.
private AdkManager mAdkManager;
8.
//...
}
9. At the bottom of the class, add a method to start the preset name recognition:
10. public void changePreset(View v) {
11.
startRecognition("Choose the current preset", VOICE_PRESET);
}
12. Implement the onRecognitionDone() callback to handle the results returned from
the recognition intent. Within this method, we call the setPreset() member
function to update the active preset and load temperature setpoints, if the given
preset is found. At the bottom of the class, add the following code:
13. @Override
14. public void onRecognitionDone(int requestCode, String bestMatch) {
15.
if (requestCode == VOICE_PRESET) {
16.
setPreset(bestMatch);
17.
}
}
18. Implement the setPreset() method to handle the best recognized result. At the
bottom of the class, add the following code:
19. private void setPreset(String name) {
20.
ArrayList<Integer> values = Preset.get(this, name);
21.
if (values.size() > 0) {
22.
Preset.setCurrent(this, name);
23.
readPreferences();
24.
}
}
25. Connect the changePreset() method that starts voice recognition with the
TextView component. In the activity_overview.xml file under res/layout/,
make the current_preset view clickable with the highlighted code:
26. <TextView
27.
android:id="@+id/current_preset"
28.
android:clickable="true"
29.
android:onClick="changePreset"
30.
android:text="NO PRESET ACTIVATED"
31.
android:gravity="center"
32.
android:textColor="@color/coral_red"
33.
android:textSize="@dimen/text_title"
34.
android:layout_width="0dp"
35.
android:layout_weight="2"
android:layout_height="match_parent" />
With this last section, we have created an abstraction to handle voice recognition through
Android intents and we have updated the Settings and the Overview activities to use it.
Now we can upload the Chronotherm application and start using the application again with
presets and voice recognition features.