2013-03-27 76 views
8

我目前正在忙於語音識別,並且我希望語音識別器能夠持續不斷地傾聽我的聲音。該應用的目的是,它將等待特定關鍵字的發言:當用戶說出這個關鍵字時,服務就準備好接收用戶語音命令。經過研究,我發現我們可以掌握識別器收聽的時間。通過這些常量:關於語音識別的Android演員陣容不起作用

順便說一句,默認識別器服務監聽大約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個mseconds,如你所見。

你能想到這個問題嗎?也許我不知道如何使用額外功能,或者它可能是關於權限,也可能是跳過我的代碼,或者我應該添加一些其他代碼。

任何幫助將appriciated。

編輯:這是我的全碼:

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實現TextToSp eech.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")); 
    } 
} 

}

+0

究竟是什麼,你想要什麼? – 2013-03-27 14:44:32

+2

我希望識別器永遠聽我說,而不是10秒鐘。它應該不斷地傾聽我的聲音。該應用將等待特定關鍵字的發言:當用戶說出這個關鍵字時,該服務就準備好接收用戶語音命令。 – Ayse 2013-03-27 14:49:24

+0

您的代碼現在在服務或活動中嗎? – 2013-03-27 14:50:36

回答

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); 
} 
+3

我沒聽索裏時相比,有什麼不同我的代碼? – Ayse 2013-03-27 15:43:29

+0

嗨,我也遇到過這個問題。你固定了嗎? – 2016-07-15 09:44:41

6

在最近的Google搜索更新中,這些參數在Jelly Bean設備中停止工作。如果有一段時間,我一直有意向提交錯誤報告。他們仍然在ICS設備和下面工作。

如果您希望繼續在沒有超時的情況下監聽關鍵字,則必須執行一個循環,從而檢查onPartialResults中的關鍵字。如果Results被調用,並且在這些中未檢測到關鍵字,則需要立即重新啓動識別。

您需要處理silent death bug並將系統音頻流靜音至prevent the Jelly Bean beep sound

這些問題使實現非常混亂和令人沮喪的。排序出來谷歌....