• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Android 语音语音识别:在 JB 4.1.2 上重复调用 SpeechRecognizer.startListening() 失败

用户头像
it1352
帮助1

问题说明

我有一项服务,我在其中反复启动语音识别侦听器,以便我可以进行开放式会话供用户发言.该类还处理 Jelly Bean 中的问题,如果在 5 秒内没有听到任何语音,则会抛出 ERROR_SPEECH_TIMEOUT.所以基本上这是有效的.但是,如果我反复调用 identifyr.startListening(recognizerIntent) ,它会默默地失败,因为在这种情况下从未调用过 onBeginningOfSpeech() 就证明了这一点.现在,如果我根本不说话,我的 Jelly Bean 超时处理程序将每次都重新启动侦听器而不会失败.它似乎只在 onResults() 被调用后失败,因为听到了语音.在 onResults() 被调用之后,recognizer.startListening(recognizerIntent) 肯定会被调用,但就像我说的,什么也没有发生.当它失败时,它是随机的,Logcat 中没有任何内容可以表明问题所在.我只是不知道还能尝试什么.希望你们中的一位 Android 语音识别专家以前见过这个......

I have a service where I'm kicking off a speech recognition listener repeatedly so I can have an open ended session for the user to speak. The class also handles the issue in Jelly Bean where a ERROR_SPEECH_TIMEOUT is thrown if no speech is heard in 5 seconds. So basically this works. However if I repeatedly call recognizer.startListening(recognizerIntent) , it silently fails as evidenced by the fact that onBeginningOfSpeech() is never called in this case. Now IF I just do not talk at all my Jelly Bean timeout handler will restart the listener every time without fail. It seems to only fail after onResults() is called because speech WAS heard. After onResults() is called, recognizer.startListening(recognizerIntent) is definitely called, but like I said, nothing happens. When it fails it is random and there is nothing in Logcat to indicate what the issue is. I just don't know what else to try. Hopefully one of you Android Speech recognition experts out there has seen this before...

最低:2.2目标:在 JB 上测试:Android 4.1.2

Minimum: 2.2 Target: Testing on JB : Android 4.1.2

更多信息 (11-01-13)我的 HTC One 的 4.3 更新确实解决了这个问题.下面我的语音识别服务现在是可靠的&准确的.我已经运行了至少几分钟没有错误.至于 4.1.2,在我更新到 4.3 之前,它似乎运行得更好(Google 是否对其进行了任何更改?)...我不知道,但它仍然会漏掉一些说过的话,偶尔也不会出错,只是停止聆听(在这种情况下永远不会调用 onBeginningOfSpeech() ).我想我只需要就这个问题就 Android 4.1.2 向我的用户发出警告,因为我已经在我的代码中尽我所能.

MORE INFO (11-01-13) The 4.3 Update to my HTC One has definitely addressed this issue. My Speech recognition service below is now reliable & accurate. I has run for at least few minutes without error. As for 4.1.2, before my update to 4.3 it seemed to have been working better (did Google change anything on their end?)...I don't know, but it still would miss some words spoken and occasionally without error, just stop listening (onBeginningOfSpeech() is never called in this case). I suppose I will just have to warn my users about Android 4.1.2 with regards to this issue because I have gone as far as I can go in my code.

更多信息 (09-17-13)据称,9 月底 HTC 的 Android 更新 (4.3) (http://www.ubergizmo.com/2013/09/htc-one-to-receive-android-4-3-jelly-bean-update-this-september/).所以希望这将解决该设备上的这个问题.对于运行 Android 4.1.2 并在该版本上停留了一段时间的我的应用程序用户来说,问题仍然存在.我仍然不知道在这些情况下该怎么做,希望这是唯一有此问题的 Android 版本.有什么办法可以查出有多少设备正在运行 4.1.2??

MORE INFO (09-17-13) Supposedly, there is an Android update (4.3) coming to HTC ones at the end of September (http://www.ubergizmo.com/2013/09/htc-one-to-receive-android-4-3-jelly-bean-update-this-september/). So hopefully that will address this issue on that device. The issue remains though for my app users that are running Android 4.1.2 and stuck on that version for a while. I still don't know what to do in those cases, and hopefully that is the ONLY Android version with this issue. Is there any way to find out how many devices are running 4.1.2??

MORE INFO (09-15-13) In this post here: Google voice recognizer doesn't starts on Android 4.x. The author state states that he is seeing this issue on his HTC one. I also have an HTC one that I'm seeing this issue on (Android 4.1.2) . I wonder if this is unique to the HTC one? (or any device running Android 4.1.2) - I can't confirm as its difficult to test on all the latest devices running JB. The author further states that his Nexxus with 4.2.2 works fine. Can anyone tell me on what device they see this issue?

更多信息 (9-08-13)为了确认我的代码没有问题,我还在 Android 2.3.3 上对此进行了测试,并且能够连续调用 onResult() > startListening() 25 次.在针对 Android 4.1.2 时,我永远无法接听 3 或 4 个电话.我不敢相信没有其他人遇到过这个问题?

MORE INFO (9-08-13) Just to confirm there is no issue with my code, I also tested this on Android 2.3.3 and I was able to call onResult() > startListening() 25 times in a row. When targeting Android 4.1.2 I'm never able to get past 3 or 4 calls. I can't believe no one else has run into this issue?

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

正确答案

#1

我在 Nexus 5 上使用 Android 4.4 KitKat,它也有同样的问题.我认为这很可能是 Android 错误,因为我还没有看到任何人提供干净的解决方案.
这个解决方案类似于 Andrew_CS 解决方案,但我认为它实际上允许更好的识别.安德鲁斯解决方案不断启动和停止识别器,您必须跟踪事物的状态,例如您是否正在处理语音.这个新的解决方案/变通方法基本上是这样做的:

I am on Android 4.4 KitKat on a Nexus 5 and it has this same issue. I think it's likely an Android bug because I haven't seen anyone with a clean solution.
This solution is similar to Andrew_CS solution but I think it's actually allows for better recognition. Andrews solution is constantly starting and stopping the recognizer and you have to keep track of the state of things like if you are processing speech or not. This new solution/work-around basically does this:

  • 一旦调用 onResults 并处理我们的结果,我们就会启动一个计时器.
  • 如果一切正常,将调用 onReadyForSpeech,我们可以取消计时器.
  • 如果事情不正常,我们的计时器会结束,我们会重新启动语音识别器并再次启动计时器.
  • 确保在 OnDestroy 方法中也取消计时器.

如果您找到更好的方法,请告诉我,但目前这似乎非常有效.如果我们真的能证明这是一个 Android 错误,我希望有人将其提交给 Google.

Please let me know if you find an even better way, but this seems to work really well for now. If we can actually prove this is an Android bug, I'd love for someone to submit it to 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();
        }

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /reply/detail/tanhcfiebg
系列文章
更多 icon
同类精品
更多 icon
继续加载