10

私は現在、音声認識で忙しいので、音声認識エンジンが私を継続的に、永遠に聞いてくれることを望んでいます。アプリの目的は、特定のキーワードの音声を待機することです。ユーザーがこのキーワードを言うと、サービスはユーザーの音声コマンドを受信できるようになります。調査の結果、認識エンジンがリッスンする時間を操作できることがわかりました。これらの定数によって:

ちなみに、デフォルトの認識サービスは約 10 秒間リッスンします。(Google 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

これらは bundle クラスのエクストラです。

問題は、コードでこれらの定数を使用すると機能しないことです。

これが私のコードです:

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

ご覧のとおり、5000 ミリ秒書き込みましたが、レコグナイザーはまだ約 10 秒間リッスンします。

問題を考えてみませんか?たぶん、エクストラの使い方がわからないか、権限に関するもので、コードをスキップするか、他のコードを追加する必要があります。

どんな助けでも感謝します。

編集:これが私の完全なコードです:

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

public class 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);
}

}

設定Activity.java

public class 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"));
    }
}

}

4

2 に答える 2

8

最近の Google 検索の更新で、これらのパラメータが Jelly Bean デバイスで機能しなくなりました。しばらくの間、if に関するバグ レポートを提出するつもりでした。ICS デバイス以下では引き続き機能します。

タイムアウトせずにキーワードをリッスンし続けたい場合は、ループを実行する必要があります。これにより、onPartialResultsでキーワードを確認します。結果が呼び出され、それらのいずれにもキーワードが検出されない場合は、すぐに認識を再開する必要があります。

サイレント デス バグを処理し、システム オーディオ ストリームをミュートして、Jelly Bean のビープ音を防ぐ必要があります。

これらの問題により、実装が非常に面倒でイライラします。Googleで並べ替えて....

于 2013-07-16T11:17:01.053 に答える
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);
}
于 2013-03-27T15:11:34.073 に答える