SpeechRecognizer causes ANR… I need help with Andr

2020-01-27 19:05发布

问题:

EDIT: I should have mentioned this already, but I'm running this code in a service. The entire app is turned on/off by a widget button and has no activity.


Update: I tried attaching the SDK sources to the project so I could get a more precise idea of where the failure was occurring, but from the looks of it, only public APIs are included, which seems to make them a lot less useful... can anyone suggest at least a debugging approach for solving this issue? I'm kind of stuck.


I'm trying to use Android's speech recognition package to record user speech and translate it to text. Unfortunately, when I attempt initiate listening, I get an ANR error that doesn't point to anything specific.

As the SpeechRecognizer API indicates, a RuntimeException is thrown if you attempt to call it from the main thread. This would make me wonder if the processing was just too demanding... but I know that other applications use the Android API for this purpose and it is typically pretty snappy.

java.lang.RuntimeException: SpeechRecognizer should be used only from the application's main thread

Here is a (trimmed) sample of the code I'm trying to call from my service. Is this the proper approach?

Thanks for taking the time to help. This has been a hurdle I haven't been able to get over yet.

Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
        RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
        "com.domain.app");

SpeechRecognizer recognizer = SpeechRecognizer
        .createSpeechRecognizer(this.getApplicationContext());
RecognitionListener listener = new RecognitionListener() {
    @Override
    public void onResults(Bundle results) {
        ArrayList<String> voiceResults = results
                .getStringArrayList(RecognizerIntent.EXTRA_RESULTS);
        if (voiceResults == null) {
            Log.e(getString(R.string.log_label), "No voice results");
        } else {
            Log.d(getString(R.string.log_label), "Printing matches: ");
            for (String match : voiceResults) {
                Log.d(getString(R.string.log_label), match);
            }
        }
    }

    @Override
    public void onReadyForSpeech(Bundle params) {
        Log.d(getString(R.string.log_label), "Ready for speech");
    }

    @Override
    public void onError(int error) {
        Log.d(getString(R.string.log_label),
                "Error listening for speech: " + error);
    }

    @Override
    public void onBeginningOfSpeech() {
        Log.d(getString(R.string.log_label), "Speech starting");
    }
};
recognizer.setRecognitionListener(listener);
recognizer.startListening(intent);

回答1:

Make Sure to use the RECORD_AUDIO permission.



回答2:

You shouldn't need to create the SpeechRecognizer class yourself, nor do you need to implement a RecognizerListener. Google made them public to be nice, but they look pretty complicated and probably for use by experts only.

To get text from the users speech yo simply need to use the RecognizerIntent.ACTION_RECOGNIZE_SPEECH to launch the built-in speech recognizer Activity and then wait for the result to come back in onActivityResult. Take a look at the example code here:

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/VoiceRecognition.html

I pulled it from this article.

http://developer.android.com/resources/articles/speech-input.html

Good Luck.



回答3:

From a service, you have to create the recognizer from looper running on the main thread. Also RecognizerIntent.EXTRA_RESULTS should be SpeechRecognizer.RESULTS_RECOGNITION.

psuedo code:

public class VoiceRecognition implements RecognitionListener, Runnable 
{
    @Override
    public void run()
    {
        recognizer = SpeechRecognizer.createSpeechRecognizer(yourContext);
        recognizer.setRecognitionListener((RecognitionListener) this);

         intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
         //... all the intent stuff ...
         intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 5);
         recognizer.startListening(intent);
    }
    @Override
    public void onResults(Bundle results)
    {
       ArrayList<String> matches;
       matches=results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
    }
 }

....
VoiceRecognition voiceRecognizer = new VoiceRecognition();
Handler loopHandler = new Handler(Looper.getMainLooper());
loopHandler.post(voiceRecognizer);


回答4:

Instead of getApplicationContext(), use this (i.e. your service instance). android.app.Service inherits from Context.



回答5:

Here is the problem I ran into, which might be related to yours. I was getting null, no matter what, from this line:

  ArrayList<String> voiceResults = results                .getStringArrayList(RecognizerIntent.EXTRA_RESULTS);  

Changing it to this completely fixed the problem:

  ArrayList<String> voiceResults = results                .getStringArrayList("results_recognition");  

I printed out the keyset from the bundle, and that was the only value. Note that the value of "results_recognition" is not the value of the string stored at RecognizerIntent.EXTRA_RESULTS. I think that's a bug, or at least it should be, since using RecognizerIntent.EXTRA_RESULTS works fine in the Activity way of doing speech recognition, but not when someone uses SpeechRecognizer.

Anyways, i most likely won't check this website again, but please email me if you have any questions, since I now do have speech recognition working without any prompts, beeps, or anything else.



回答6:

I got this to work by installing the Google Voice App