Android Speech Распознавание речи: повторный вызов SpeechRecognizer.startListening () не работает на JB 4.1.2

У меня есть служба, в которой я начинаю прослушивать речевой речевой сигнал повторно, чтобы у меня была открытая сессия для того, чтобы пользователь мог говорить. Класс также обрабатывает проблему в Jelly Bean, где вызывается ERROR_SPEECH_TIMEOUT, если в течение 5 секунд не слышно речи. Так что в основном это работает. Однако, если я неоднократно вызываю функцию распознавания.startListening (распознающий элемент), он бесшумно терпит неудачу, о чем свидетельствует тот факт, что onBeginningOfSpeech () никогда не вызывается в этом случае. Теперь, если я просто не буду говорить, мой обработчик тайм-аута Jelly Bean будет перезапускать слушателя каждый раз в обязательном порядке. Кажется, он только терпит неудачу после того, как onResults () вызвана, потому что речь была услышана. Когда вызывается onResults (), распознавание распознавания.startListening (identizerIntent) определенно называется, но, как я уже сказал, ничего не происходит. Когда он терпит неудачу, он случайный, и в Logcat нет ничего, чтобы указать, в чем проблема. Я просто не знаю, что еще попробовать. Надеюсь, один из вас, специалисты по распознаванию речи в Android, увидели это раньше …

Минимум: 2,2 Цель: Тестирование на JB: Android 4.1.2


ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ (11-01-13) 4.3 Обновление для моего HTC One определенно решило эту проблему. Теперь моя служба распознавания речи является надежной и точной. Я пропустил хотя бы несколько минут без ошибок. Что касается 4.1.2, то до моего обновления до 4.3 он, казалось, работал лучше (изменил ли Google что-нибудь на их конце?) … Я не знаю, но он все равно пропустит некоторые слова, произнесенные и иногда без ошибок, Просто прекратите слушать (onBeginningOfSpeech () в этом случае никогда не вызывается). Полагаю, мне просто нужно предупредить моих пользователей об Android 4.1.2 в отношении этой проблемы, потому что я дошел до моего кода.

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ (09-17-13) Предположительно, в конце сентября в HTC появится обновление Android (4.3) ( http://www.ubergizmo.com/2013/09/htc-one-to-receive -андроид-4-3-желе-боб-обновление-это-сентябрь / ). Надеемся, что эта проблема будет рассмотрена на этом устройстве. Проблема остается, хотя для моих пользователей приложений, которые работают под управлением Android 4.1.2, и застрял в этой версии некоторое время. Я до сих пор не знаю, что делать в этих случаях, и, надеюсь, это единственная версия Android с этой проблемой. Есть ли способ узнать, сколько устройств работает 4.1.2?

БОЛЬШЕ ИНФОРМАЦИИ (09-15-13) В этом сообщении здесь: Google voice распознаватель не запускается на Android 4.x. В заявлении автора говорится, что он видит этот вопрос на своем HTC. У меня также есть HTC, который я вижу в этой проблеме (Android 4.1.2). Интересно, это уникально для HTC? (Или любое устройство под управлением Android 4.1.2). Я не могу подтвердить, так как его трудно проверить на всех последних устройствах под управлением JB. Далее автор утверждает, что его Nexxus с 4.2.2 отлично работает. Может ли кто-нибудь сказать мне, на каком устройстве они видят эту проблему?

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ (9-08-13) Просто чтобы подтвердить, что с моим кодом нет проблем, я также тестировал это на Android 2.3.3, и мне удалось вызвать onResult ()> startListening () 25 раз подряд. При таргетинге на Android 4.1.2 я никогда не смог пройти 3 или 4 вызова. Не могу поверить, что никто другой не столкнулся с этой проблемой?

public class VoiceRecogService extends Service { protected AudioManager mAudioManager; protected SpeechRecognizer mSpeechRecognizer; protected Intent mSpeechRecognizerIntent; protected RecognitionListener mSpeechRecognizerListner; //protected final Messenger mServerMessenger = new Messenger(new IncomingHandler(this)); protected volatile boolean mIsListening; protected volatile boolean mIsCountDownOn; static final int MSG_RECOGNIZER_START_LISTENING = 1; static final int MSG_RECOGNIZER_CANCEL = 2; private int mBindFlag; private Messenger mServiceMessenger; private Context m_ctx; private Handler mHandler = new Handler(); //private boolean m_bReadyForSpeechReceived = false; @Override public void onCreate() { super.onCreate(); m_ctx = this; mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); //do not mute beep when speech listening first kicks off Log.d("TESTING: SPEECH SERVICE: CALL START", "onCreate()"); startListening(false); } private void startListening(boolean bMuteSound){ Log.d("TESTING: SPEECH SERVICE: startListening()", mIsListening? "true":"false"); if (bMuteSound==true && Build.VERSION.SDK_INT >= 16)//Build.VERSION_CODES.JELLY_BEAN) { // turn off beep sound mAudioManager.setStreamMute(AudioManager.STREAM_SYSTEM, true); } if (!mIsListening) { //mSpeechRecognizer.startListening(mSpeechRecognizerIntent); recognizeSpeechDirectly (); mIsListening = true; } } ///////////////////////////////////////////////////////////////////////// /** * lazy initialize the speech recognizer */ private SpeechRecognizer getSpeechRecognizer() { if (mSpeechRecognizer == null) { mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(m_ctx); } return mSpeechRecognizer; } private RecognitionListener getSpeechRecognizerListner() { if (mSpeechRecognizerListner == null) { mSpeechRecognizerListner = new SpeechRecognitionListener(); } return mSpeechRecognizerListner; } private void recognizeSpeechDirectly() { Intent recognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); // accept partial results if they come recognizerIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true); recognizeSpeechDirectly(m_ctx,recognizerIntent, getSpeechRecognizerListner(), getSpeechRecognizer()); } public static void recognizeSpeechDirectly(Context context, Intent recognizerIntent, RecognitionListener listener, SpeechRecognizer recognizer) { //need to have a calling package for it to work if (!recognizerIntent.hasExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE)) { recognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, "com.dummy"); } recognizer.setRecognitionListener(listener); recognizer.startListening(recognizerIntent); } //////////////////////////////////////////////////////////////////////////// public void stop() { if (getSpeechRecognizer() != null) { getSpeechRecognizer().stopListening(); getSpeechRecognizer().cancel(); getSpeechRecognizer().destroy(); mIsListening = false; if (Build.VERSION.SDK_INT >= 16);//Build.VERSION_CODES.JELLY_BEAN) mAudioManager.setStreamMute(AudioManager.STREAM_SYSTEM, false); } } // Count down timer for Jelly Bean work around protected CountDownTimer mNoSpeechCountDown = new CountDownTimer(5000, 5000) { @Override public void onTick(long millisUntilFinished) { // TODO Auto-generated method stub } @Override public void onFinish() { mIsCountDownOn = false; Log.d("TESTING: SPEECH SERVICE: CALL START", "onFinish()"); startListening(true); } }; @Override public void onDestroy() { super.onDestroy(); if (mIsCountDownOn) { mNoSpeechCountDown.cancel(); } if (mSpeechRecognizer != null) { mSpeechRecognizer.destroy(); } } protected class SpeechRecognitionListener implements RecognitionListener { @Override public void onReadyForSpeech(Bundle params) { if (Build.VERSION.SDK_INT >= 16)//Build.VERSION_CODES.JELLY_BEAN) { mIsCountDownOn = true; mNoSpeechCountDown.start(); } Log.d("TESTING: SPEECH SERVICE", "onReadyForSpeech"); } @Override public void onBeginningOfSpeech() { // speech input will be processed, so there is no need for count down anymore if (mIsCountDownOn) { mIsCountDownOn = false; mNoSpeechCountDown.cancel(); } } @Override public void onEndOfSpeech() { Log.d("TESTING: SPEECH SERVICE", "onEndOfSpeech"); } @Override public void onBufferReceived(byte[] buffer) { //Log.d("TESTING: SPEECH SERVICE", buffer + new String(new byte[] {0x63})); } @Override public void onError(int error) { if ((error == SpeechRecognizer.ERROR_NO_MATCH) || (error == SpeechRecognizer.ERROR_SPEECH_TIMEOUT)){ if (mIsCountDownOn) { mIsCountDownOn = false; mNoSpeechCountDown.cancel(); } mIsListening = false; Log.d("TESTING: SPEECH SERVICE: CALL START", "onError()"); startListening(true); } } @Override public void onEvent(int eventType, Bundle params) { } @Override public void onPartialResults(Bundle partialResults) { } @Override public void onResults(Bundle results) { //String str = new String(); //Log.d(TAG, "onResults " + results); ArrayList data = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); //if(data.size() >=1){ // //check for save it: //} for (int i = 0; i < data.size(); i++) { Log.d("TESTING: SPEECH SERVICE", (String)data.get(i)); } //if no "save it" somewhere in there, then continue: if (mIsCountDownOn) { mIsCountDownOn = false; } mIsListening = false; Log.d("TESTING: SPEECH SERVICE: CALL START", "onResults()"); startListening(true); } @Override public void onRmsChanged(float rmsdB) { } } @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null; } } 

Solutions Collecting From Web of "Android Speech Распознавание речи: повторный вызов SpeechRecognizer.startListening () не работает на JB 4.1.2"

Я на Android 4.4 KitKat на Nexus 5, и у него есть эта же проблема. Я думаю, что это, вероятно, ошибка Android, потому что я не видел никого с чистым решением.
Это решение похоже на решение Andrew_CS, но я думаю, что это фактически позволяет лучше распознавать. Решение Andrews постоянно запускает и останавливает распознаватель, и вы должны отслеживать состояние вещей, например, если вы обрабатываете речь или нет. Это новое решение / work-around в основном делает это:

  • Когда вызывается onResults и наши результаты обрабатываются, мы запускаем таймер.
  • Если все будет работать правильно, будет вызван onReadyForSpeech, и мы можем отменить наш таймер.
  • Если что-то не работает должным образом, наш таймер заканчивается, и мы перезапускаем распознаватель речи и снова запускаем таймер.
  • Убедитесь, что вы отменили таймер в методе OnDestroy.

Пожалуйста, дайте мне знать, если вы найдете еще лучший способ, но сейчас это работает очень хорошо. Если мы действительно докажем, что это ошибка Android, я бы хотел, чтобы кто-то отправил ее в Google.

  @Override public void onReadyForSpeech(Bundle params) { Log.d("Speech", "onReadyForSpeech: Cancel Timer"); if(mTimer != null) { mTimer.cancel(); } } @Override public void onResults(Bundle results) { //If the timer is available, cancel it so it doesn't interrupt our result processing if(mTimer != null){ mTimer.cancel(); } Log.d("Speech", "onResults"); //Start processing data ArrayList<String> strlist = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); for (int i = 0; i < strlist.size();i++ ) { Log.d("Speech", "YOU SAID: " + strlist.get(i)); } //Start listening again Log.d("Speech", "onResults: Start Listening"); mSpeechRecognizer.startListening(mRecognizerIntent); //Start a timer in case OnReadyForSpeech is never called back (Android Bug?) Log.d("Speech", "onResults: Start a timer"); if(mTimer == null) { mTimer = new CountDownTimer(2000, 500) { @Override public void onTick(long l) { } @Override public void onFinish() { Log.d("Speech", "Timer.onFinish: Timer Finished, Restart recognizer"); mSpeechRecognizer.cancel(); mSpeechRecognizer.startListening(mRecognizerIntent); } }; } mTimer.start(); } 

Вы можете использовать:

 intent.putExtra("android.speech.extra.DICTATION_MODE", true); 

Этот код заставит службу прослушать длительное время.

Чтобы обойти эту проблему, я использовал CountDownTimer для постепенного вызова отмены и началаListening.

 _timer = new CountDownTimer(300000000, 1000){ @Override public void onTick(long millisUntilFinished){ if(!_processingSpeech){ _mSpeechRecognizer.cancel(); _mSpeechRecognizer.startListening(_mSpeechRecognizerIntent); } } @Override public void onFinish(){ setUpTimer(); } }; _processingSpeech = false; _timer.start(); 

Я использовал логическую обработкуSpeech в методах RecognitionListener, чтобы убедиться, что я не отменял и не перезапускал, пока я получал / обрабатывал входные данные.

Дайте мне знать, если это вам поможет, или вам нужна дополнительная информация. Удачи!

Попробуйте использовать один экземпляр SpeechRecognizer , не нужно воссоздавать его по методу stop () . Вызовите getSpeechRecognizer () на onCreate () и забудьте об этом. Но не забудьте уничтожить метод onDestroy ().