有关语音识别的Android附加功能不起作用

时间:2013-03-27 14:02:23

标签: android speech-recognition speech-to-text

我目前正在忙于语音识别,我希望语音识别器能够永远地听我说话。该应用程序的目的是,它将等待特定关键字的语音:当用户说出此关键字时,该服务已准备好接收用户语音命令经过研究,我发现我们可以完成识别器监听的时间。通过这些常数:

顺便说一下,默认的识别器服务会监听大约10秒钟。 (谷歌api)

     String EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS   The amount of time that it should take after we stop hearing speech to consider the input complete.
     String EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS    The minimum length of an utterance.
     String EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS  The amount of time that it should take after we stop hearing speech to consider the input possibly complete.

http://java.llp2.dcc.ufmg.br/apiminer/docs/reference/android/speech/RecognizerIntent.html

这些是捆绑类的附加内容。

问题是,当我在我的代码中使用这些常量时,它不起作用。

这是我的代码:

   intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
   intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, 5000);
   intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 5000);

识别器仍然会听我大约10秒,虽然我写了5000毫秒,如你所见。

你能想到这个问题吗?也许我不知道如何使用额外内容或者它是关于权限,也许它会跳过我的代码或者我应该添加一些其他代码。

任何帮助都会得到满足。

编辑:这是我的完整代码:

VoiceRecognitionActivity.java

public class VoiceRecognitionActivity extends Activity implements
    TextToSpeech.OnInitListener {

private static final int REQUEST_CODE = 1234;
private Button mTalkButton;
private ListView wordsList;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_voice_recognition);
    mTalkButton = (Button) findViewById(R.id.talk_button);
    wordsList = (ListView) findViewById(R.id.listView1);
    // Disable button if no recognition service is present
    PackageManager pm = getPackageManager();
    List<ResolveInfo> activities = pm.queryIntentActivities(new Intent(
            RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
    if (activities.size() == 0) {
        mTalkButton.setEnabled(false);
        mTalkButton.setText("Recognizer not present");
    } else {
        mTalkButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(
                        RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                        RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
                intent.putExtra(RecognizerIntent.EXTRA_PROMPT,
                        "Voice recognition Demo...");
                String defaultLanguage = Locale
                        .getDefault().toString();
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale
                        .getDefault());

                intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
                intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, 5000);
                intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 5000);

                startActivityForResult(intent, REQUEST_CODE);

            }
        });
    }
}

/**
 * Handle the results from the voice recognition activity.
 */
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
        // Populate the wordsList with the String values the recognition
        // engine thought it heard
        ArrayList<String> matches = data
                .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
        wordsList.setAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, matches));
    }
    super.onActivityResult(requestCode, resultCode, data);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_voice_recognition, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle item selection
    switch (item.getItemId()) {
    case R.id.menu_settings:
        startActivity(new Intent(this, SettingsActivity.class));
        return true;

    default:
        return super.onOptionsItemSelected(item);
    }
}

@Override
public void onInit(int status) {
    // TODO Auto-generated method stub

}

}

TTSUtils.java

公共类TTSUtils实现了TextToSpeech.OnInitListener {

private TextToSpeech mTts;
private static TTSUtils mInstance;
private Context mContext;

public static TTSUtils getInstance(Context c) {
    if (mInstance == null) {
        mInstance = new TTSUtils(c);
    }
    return mInstance;
}

private TTSUtils(Context c) {
    mContext = c;
    mTts = new TextToSpeech(mContext, this);
    mInstance = this;
}

@Override
public void onInit(int status) {
    // TODO Auto-generated method stub

}

public void destroyTTS() {
    if (mTts != null) {
        mTts.stop();
        mTts.shutdown();
    }
}

public int setLanguage(Locale l) {
    return mTts.setLanguage(l);
}

public int speak(String s, int i, HashMap<String, String> h) {
    return mTts.speak(s, i, h);
}

}

SettingsActivity.java

公共类SettingsActivity扩展了PreferenceActivity {

/**
 * Determines whether to always show the simplified settings UI, where
 * settings are presented in a single list. When false, settings are shown
 * as a master/detail two-pane view on tablets. When true, a single pane is
 * shown on tablets.
 */

private static final boolean ALWAYS_SIMPLE_PREFS = false;

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);

    setupSimplePreferencesScreen();
}

/**
 * Shows the simplified settings UI if the device configuration if the
 * device configuration dictates that a simplified, single-pane UI should be
 * shown.
 */
private void setupSimplePreferencesScreen() {
    if (!isSimplePreferences(this)) {
        return;
    }

    // In the simplified UI, fragments are not used at all and we instead
    // use the older PreferenceActivity APIs.

    // Add 'general' preferences.
    addPreferencesFromResource(R.xml.pref_general);

    // Add 'notifications' preferences, and a corresponding header.
    PreferenceCategory fakeHeader = new PreferenceCategory(this);
    fakeHeader.setTitle(R.string.pref_header_notifications);
    getPreferenceScreen().addPreference(fakeHeader);
    addPreferencesFromResource(R.xml.pref_notification);

    // Add 'data and sync' preferences, and a corresponding header.
    fakeHeader = new PreferenceCategory(this);
    fakeHeader.setTitle(R.string.pref_header_data_sync);
    getPreferenceScreen().addPreference(fakeHeader);
    addPreferencesFromResource(R.xml.pref_data_sync);

    // Bind the summaries of EditText/List/Dialog/Ringtone preferences to
    // their values. When their values change, their summaries are updated
    // to reflect the new value, per the Android Design guidelines.
    bindPreferenceSummaryToValue(findPreference("example_text"));
    bindPreferenceSummaryToValue(findPreference("example_list"));
    bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
    bindPreferenceSummaryToValue(findPreference("sync_frequency"));
}

/** {@inheritDoc} */
@Override
public boolean onIsMultiPane() {
    return isXLargeTablet(this) && !isSimplePreferences(this);
}

/**
 * Helper method to determine if the device has an extra-large screen. For
 * example, 10" tablets are extra-large.
 */
private static boolean isXLargeTablet(Context context) {
    return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}

/**
 * Determines whether the simplified settings UI should be shown. This is
 * true if this is forced via {@link #ALWAYS_SIMPLE_PREFS}, or the device
 * doesn't have newer APIs like {@link PreferenceFragment}, or the device
 * doesn't have an extra-large screen. In these cases, a single-pane
 * "simplified" settings UI should be shown.
 */
private static boolean isSimplePreferences(Context context) {
    return ALWAYS_SIMPLE_PREFS
            || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB
            || !isXLargeTablet(context);
}

/** {@inheritDoc} */
@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
    if (!isSimplePreferences(this)) {
        loadHeadersFromResource(R.xml.pref_headers, target);
    }
}

/**
 * A preference value change listener that updates the preference's summary
 * to reflect its new value.
 */
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
    @Override
    public boolean onPreferenceChange(Preference preference, Object value) {
        String stringValue = value.toString();

        if (preference instanceof ListPreference) {
            // For list preferences, look up the correct display value in
            // the preference's 'entries' list.
            ListPreference listPreference = (ListPreference) preference;
            int index = listPreference.findIndexOfValue(stringValue);

            // Set the summary to reflect the new value.
            preference
                    .setSummary(index >= 0 ? listPreference.getEntries()[index]
                            : null);

        } else if (preference instanceof RingtonePreference) {
            // For ringtone preferences, look up the correct display value
            // using RingtoneManager.
            if (TextUtils.isEmpty(stringValue)) {
                // Empty values correspond to 'silent' (no ringtone).
                preference.setSummary(R.string.pref_ringtone_silent);

            } else {
                Ringtone ringtone = RingtoneManager.getRingtone(
                        preference.getContext(), Uri.parse(stringValue));

                if (ringtone == null) {
                    // Clear the summary if there was a lookup error.
                    preference.setSummary(null);
                } else {
                    // Set the summary to reflect the new ringtone display
                    // name.
                    String name = ringtone
                            .getTitle(preference.getContext());
                    preference.setSummary(name);
                }
            }

        } else {
            // For all other preferences, set the summary to the value's
            // simple string representation.
            preference.setSummary(stringValue);
        }
        return true;
    }
};

/**
 * Binds a preference's summary to its value. More specifically, when the
 * preference's value is changed, its summary (line of text below the
 * preference title) is updated to reflect the value. The summary is also
 * immediately updated upon calling this method. The exact display format is
 * dependent on the type of preference.
 * 
 * @see #sBindPreferenceSummaryToValueListener
 */
private static void bindPreferenceSummaryToValue(Preference preference) {
    // Set the listener to watch for value changes.
    preference
            .setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);

    // Trigger the listener immediately with the preference's
    // current value.
    sBindPreferenceSummaryToValueListener.onPreferenceChange(
            preference,
            PreferenceManager.getDefaultSharedPreferences(
                    preference.getContext()).getString(preference.getKey(),
                    ""));
}

/**
 * This fragment shows general preferences only. It is used when the
 * activity is showing a two-pane settings UI.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GeneralPreferenceFragment extends PreferenceFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.pref_general);

        // Bind the summaries of EditText/List/Dialog/Ringtone preferences
        // to their values. When their values change, their summaries are
        // updated to reflect the new value, per the Android Design
        // guidelines.
        bindPreferenceSummaryToValue(findPreference("example_text"));
        bindPreferenceSummaryToValue(findPreference("example_list"));
    }
}

/**
 * This fragment shows notification preferences only. It is used when the
 * activity is showing a two-pane settings UI.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class NotificationPreferenceFragment extends
        PreferenceFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.pref_notification);

        // Bind the summaries of EditText/List/Dialog/Ringtone preferences
        // to their values. When their values change, their summaries are
        // updated to reflect the new value, per the Android Design
        // guidelines.
        bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
    }
}

/**
 * This fragment shows data and sync preferences only. It is used when the
 * activity is showing a two-pane settings UI.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class DataSyncPreferenceFragment extends PreferenceFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.pref_data_sync);

        // Bind the summaries of EditText/List/Dialog/Ringtone preferences
        // to their values. When their values change, their summaries are
        // updated to reflect the new value, per the Android Design
        // guidelines.
        bindPreferenceSummaryToValue(findPreference("sync_frequency"));
    }
}

}

2 个答案:

答案 0 :(得分:6)

这些参数在最近的Google搜索更新中停止了Jelly Bean设备的使用。我一直想提交关于if一段时间的错误报告。它们仍适用于ICS设备及其下方。

如果您希望在没有超时的情况下继续侦听关键字,则必须执行循环,从而在onPartialResults中检查关键字。如果调用Results并且未检测到关键字,则需要立即重新启动识别。

您需要处理silent death bug并将系统音频流静音为prevent the Jelly Bean beep sound

这些问题使得实施非常混乱和令人沮丧。把它排除在谷歌....

答案 1 :(得分:1)

这项工作仅适用于果冻豆

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
    // Populate the wordsList with the String values the recognition
    // engine thought it heard
    ArrayList<String> matches = data
            .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
    wordsList.setAdapter(new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_1, matches));
}
else {
finishActivity(REQUEST_CODE);
          startAndroidVoiceRecognition();
}
super.onActivityResult(requestCode, resultCode, data);
}  

public startAndroidVoiceRecognition()
{
    Intent intent = new Intent(
                    RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
            intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                    RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
            intent.putExtra(RecognizerIntent.EXTRA_PROMPT,
                    "Voice recognition Demo...");
            String defaultLanguage = Locale
                    .getDefault().toString();
            intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale
                    .getDefault());
    startActivityForResult(intent, REQUEST_CODE);
}