FileDocCategorySizeDatePackage
VoiceDialerActivity.javaAPI DocAndroid 1.5 API19261Wed May 06 22:42:48 BST 2009com.android.voicedialer

VoiceDialerActivity

public 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
Constructors Summary
Methods Summary
private java.lang.StringgetArg(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.BundlegetRecognitionResult()
Returns a Bundle with the result for a test run

return
Bundle or null if the test is in progress

        return null;
    
private static java.io.FilenewFile(java.lang.String name)

        return name != null ? new File(name) : null;
    
private voidnotifyText(java.lang.CharSequence msg)

        Toast.makeText(VoiceDialerActivity.this, msg, Toast.LENGTH_SHORT).show();
    
protected voidonCreate(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 voidonDestroy()

        super.onDestroy();
    
public voidonMicrophoneStart()
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 voidonPause()

        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 voidonRecognitionError(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 voidonRecognitionFailure(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 voidonRecognitionSuccess(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.

param
intents a list of Intents corresponding to the sentences.

        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 intplaySound(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 voidstartNextTest()

        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 voidstartWork()


       
        // 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();