VoiceDialerActivitypublic class VoiceDialerActivity extends android.app.Activity This class is the user interface of the VoiceDialer application.
Its life cycle is as follows:
- The user presses the recognize key, and the VoiceDialerActivity starts.
- A {@link RecognizerEngine} instance is created.
- The RecognizerEngine signals the user to speak with the Vibrator.
- The RecognizerEngine captures, processes, and recognizes speech
against the names in the contact list.
- The RecognizerEngine calls onRecognizerSuccess with a list of
sentences and corresponding Intents.
- If the list is one element long, the corresponding Intent is dispatched.
- Else an {@link AlertDialog} containing the list of sentences is
displayed.
- The user selects the desired sentence from the list,
and the corresponding Intent is dispatched.
Notes:
- The RecognizerEngine is kept and reused for the next recognition cycle.
|
Fields Summary |
---|
private static final String | TAG | private static final String | MICROPHONE_EXTRA | private static final String | CONTACTS_EXTRA | private static final String | CODEC_EXTRA | private static final String | TONE_EXTRA | private static final int | FAIL_PAUSE_MSEC | private static final com.android.voicedialer.RecognizerEngine | mEngine | private VoiceDialerTester | mVoiceDialerTester | private android.os.Handler | mHandler | private Thread | mRecognizerThread | private android.media.AudioManager | mAudioManager | private android.media.ToneGenerator | mToneGenerator | private android.bluetooth.BluetoothHeadset | mBluetoothHeadset | private BluetoothHeadset.ServiceListener | mBluetoothHeadsetServiceListener | private Runnable | mMicFlasher |
Methods Summary |
---|
private java.lang.String | getArg(java.lang.String name)
if (name == null) return null;
String arg = getIntent().getStringExtra(name);
if (arg != null) return arg;
arg = SystemProperties.get("app.voicedialer." + name);
return arg != null && arg.length() > 0 ? arg : null;
| public android.os.Bundle | getRecognitionResult()Returns a Bundle with the result for a test run
return null;
| private static java.io.File | newFile(java.lang.String name)
return name != null ? new File(name) : null;
| private void | notifyText(java.lang.CharSequence msg)
Toast.makeText(VoiceDialerActivity.this, msg, Toast.LENGTH_SHORT).show();
| protected void | onCreate(android.os.Bundle icicle)
super.onCreate(icicle);
if (Config.LOGD) Log.d(TAG, "onCreate");
mHandler = new Handler();
mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
// tell music player to shut up so we can hear
Intent i = new Intent("com.android.music.musicservicecommand");
i.putExtra("command", "pause");
sendBroadcast(i);
// set up ToneGenerator
// currently disabled because it crashes audio input
mToneGenerator = !"0".equals(getArg(TONE_EXTRA)) ?
new ToneGenerator(AudioManager.STREAM_RING, ToneGenerator.MAX_VOLUME) :
null;
// open main window
setTheme(android.R.style.Theme_Dialog);
setTitle(R.string.title);
setContentView(R.layout.voice_dialing);
findViewById(R.id.microphone_view).setVisibility(View.INVISIBLE);
findViewById(R.id.retry_view).setVisibility(View.INVISIBLE);
findViewById(R.id.microphone_loading_view).setVisibility(View.VISIBLE);
if (RecognizerLogger.isEnabled(this)) {
((TextView)findViewById(R.id.substate)).setText(R.string.logging_enabled);
}
// throw up tooltip
if (false && !Intent.ACTION_VOICE_COMMAND.equals(getIntent().getAction())) {
View v = getLayoutInflater().inflate(R.layout.tool_tip, null);
Toast toast = new Toast(this);
toast.setView(v);
toast.setDuration(Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM, 0, 0);
toast.show();
}
// start the tester, if present
mVoiceDialerTester = null;
File micDir = newFile(getArg(MICROPHONE_EXTRA));
if (micDir != null && micDir.isDirectory()) {
mVoiceDialerTester = new VoiceDialerTester(micDir);
startNextTest();
return;
}
// Get handle to BluetoothHeadset object if required
if (!BluetoothHeadset.DISABLE_BT_VOICE_DIALING &&
Intent.ACTION_VOICE_COMMAND.equals(getIntent().getAction())) {
// start work in the BluetoothHeadsetClient onServiceConnected() callback
mBluetoothHeadset = new BluetoothHeadset(this, mBluetoothHeadsetServiceListener);
} else {
startWork();
}
| protected void | onDestroy()
super.onDestroy();
| public void | onMicrophoneStart()Called by the {@link RecognizerEngine} when the microphone is started.
if (Config.LOGD) Log.d(TAG, "onMicrophoneStart");
if (mVoiceDialerTester != null) return;
mHandler.post(new Runnable() {
public void run() {
findViewById(R.id.microphone_loading_view).setVisibility(View.INVISIBLE);
((TextView)findViewById(R.id.state)).setText(R.string.listening);
mHandler.post(mMicFlasher);
}
});
| protected void | onPause()
super.onPause();
if (Config.LOGD) Log.d(TAG, "onPause");
// shut down bluetooth, if it exists
if (mBluetoothHeadset != null) {
mBluetoothHeadset.stopVoiceRecognition();
mBluetoothHeadset.close();
mBluetoothHeadset = null;
}
// no more tester
mVoiceDialerTester = null;
// shut down recognizer and wait for the thread to complete
if (mRecognizerThread != null) {
mRecognizerThread.interrupt();
try {
mRecognizerThread.join();
} catch (InterruptedException e) {
if (Config.LOGD) Log.d(TAG, "onPause mRecognizerThread.join exception " + e);
}
mRecognizerThread = null;
}
// clean up UI
mHandler.removeCallbacks(mMicFlasher);
mHandler.removeMessages(0);
// clean up ToneGenerator
if (mToneGenerator != null) {
mToneGenerator.release();
mToneGenerator = null;
}
// bye
finish();
| public void | onRecognitionError(java.lang.String msg)Called by the {@link RecognizerEngine} on an internal error.
if (Config.LOGD) Log.d(TAG, "onRecognitionError " + msg);
// get work off UAPI thread
mHandler.post(new Runnable() {
public void run() {
// error, so beep about it
playSound(ToneGenerator.TONE_PROP_NACK);
mHandler.removeCallbacks(mMicFlasher);
((TextView)findViewById(R.id.state)).setText(R.string.please_try_again);
((TextView)findViewById(R.id.substate)).setText(R.string.recognition_error);
findViewById(R.id.state).setVisibility(View.VISIBLE);
findViewById(R.id.microphone_view).setVisibility(View.INVISIBLE);
findViewById(R.id.retry_view).setVisibility(View.VISIBLE);
if (mVoiceDialerTester != null) {
mVoiceDialerTester.onRecognitionError(msg);
startNextTest();
return;
}
mHandler.postDelayed(new Runnable() {
public void run() {
finish();
}
}, FAIL_PAUSE_MSEC);
}
});
| public void | onRecognitionFailure(java.lang.String msg)Called by the {@link RecognizerEngine} if the recognizer fails.
if (Config.LOGD) Log.d(TAG, "onRecognitionFailure " + msg);
// get work off UAPI thread
mHandler.post(new Runnable() {
public void run() {
// failure, so beep about it
playSound(ToneGenerator.TONE_PROP_NACK);
mHandler.removeCallbacks(mMicFlasher);
((TextView)findViewById(R.id.state)).setText(R.string.please_try_again);
findViewById(R.id.state).setVisibility(View.VISIBLE);
findViewById(R.id.microphone_view).setVisibility(View.INVISIBLE);
findViewById(R.id.retry_view).setVisibility(View.VISIBLE);
if (mVoiceDialerTester != null) {
mVoiceDialerTester.onRecognitionFailure(msg);
startNextTest();
return;
}
mHandler.postDelayed(new Runnable() {
public void run() {
finish();
}
}, FAIL_PAUSE_MSEC);
}
});
| public void | onRecognitionSuccess(android.content.Intent[] intents)Called by the {@link RecognizerEngine} when is succeeds. If there is
only one item, then the Intent is dispatched immediately.
If there are more, then an AlertDialog is displayed and the user is
prompted to select.
if (Config.LOGD) Log.d(TAG, "onRecognitionSuccess " + intents.length);
mHandler.post(new Runnable() {
public void run() {
// success, so beep about it
playSound(ToneGenerator.TONE_PROP_ACK);
mHandler.removeCallbacks(mMicFlasher);
// only one item, so just launch
/*
if (intents.length == 1 && mVoiceDialerTester == null) {
// start the Intent
startActivityHelp(intents[0]);
finish();
return;
}
*/
DialogInterface.OnClickListener clickListener =
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (Config.LOGD) Log.d(TAG, "clickListener.onClick " + which);
startActivityHelp(intents[which]);
dialog.dismiss();
finish();
}
};
DialogInterface.OnCancelListener cancelListener =
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
if (Config.LOGD) Log.d(TAG, "cancelListener.onCancel");
dialog.dismiss();
finish();
}
};
DialogInterface.OnClickListener positiveListener =
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (Config.LOGD) Log.d(TAG, "positiveListener.onClick " + which);
if (intents.length == 1 && which == -1) which = 0;
startActivityHelp(intents[which]);
dialog.dismiss();
finish();
}
};
DialogInterface.OnClickListener negativeListener =
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (Config.LOGD) Log.d(TAG, "negativeListener.onClick " + which);
dialog.dismiss();
finish();
}
};
String[] sentences = new String[intents.length];
for (int i = 0; i < intents.length; i++) {
sentences[i] = intents[i].getStringExtra(
RecognizerEngine.SENTENCE_EXTRA);
}
final AlertDialog alertDialog = intents.length > 1 ?
new AlertDialog.Builder(VoiceDialerActivity.this)
.setTitle(R.string.title)
.setItems(sentences, clickListener)
.setOnCancelListener(cancelListener)
.setNegativeButton(android.R.string.cancel, negativeListener)
.show()
:
new AlertDialog.Builder(VoiceDialerActivity.this)
.setTitle(R.string.title)
.setItems(sentences, clickListener)
.setOnCancelListener(cancelListener)
.setPositiveButton(android.R.string.ok, positiveListener)
.setNegativeButton(android.R.string.cancel, negativeListener)
.show();
// start the next test
if (mVoiceDialerTester != null) {
mVoiceDialerTester.onRecognitionSuccess(intents);
startNextTest();
mHandler.postDelayed(new Runnable() {
public void run() {
alertDialog.dismiss();
}
}, 2000);
}
}
// post a Toast if not real contacts or microphone
private void startActivityHelp(Intent intent) {
if (getArg(MICROPHONE_EXTRA) == null &&
getArg(CONTACTS_EXTRA) == null) {
startActivity(intent);
} else {
notifyText(intent.
getStringExtra(RecognizerEngine.SENTENCE_EXTRA) +
"\n" + intent.toString());
}
}
});
| private int | playSound(int toneType)
int msecDelay = 1;
// use the MediaPlayer to prompt the user
if (mToneGenerator != null) {
mToneGenerator.startTone(toneType);
msecDelay = StrictMath.max(msecDelay, 300);
}
// use the Vibrator to prompt the user
if ((mAudioManager != null) && (mAudioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER))) {
final int VIBRATOR_TIME = 150;
final int VIBRATOR_GUARD_TIME = 150;
Vibrator vibrator = new Vibrator();
vibrator.vibrate(VIBRATOR_TIME);
msecDelay = StrictMath.max(msecDelay,
VIBRATOR_TIME + VIBRATOR_GUARD_TIME);
}
return msecDelay;
| private void | startNextTest()
mHandler.postDelayed(new Runnable() {
public void run() {
if (mVoiceDialerTester == null) {
return;
}
if (!mVoiceDialerTester.stepToNextTest()) {
mVoiceDialerTester.report();
notifyText("Test completed!");
finish();
return;
}
File microphone = mVoiceDialerTester.getWavFile();
File contacts = newFile(getArg(CONTACTS_EXTRA));
String codec = getArg(CODEC_EXTRA);
notifyText("Testing\n" + microphone + "\n" + contacts);
mEngine.recognize(VoiceDialerActivity.this,
microphone, contacts, codec);
}
}, 2000);
| private void | startWork()
// prompt the user with a beep
final int msec = playSound(ToneGenerator.TONE_PROP_PROMPT);
// start the engine after the beep
mRecognizerThread = new Thread() {
public void run() {
if (Config.LOGD) Log.d(TAG, "onCreate.Runnable.run");
try {
Thread.sleep(msec);
} catch (InterruptedException e) {
return;
}
if (mToneGenerator != null) mToneGenerator.stopTone();
mEngine.recognize(VoiceDialerActivity.this,
newFile(getArg(MICROPHONE_EXTRA)),
newFile(getArg(CONTACTS_EXTRA)),
getArg(CODEC_EXTRA));
}
};
mRecognizerThread.start();
|
|