SpeechRecognizer вызывает ANR... Мне нужна помощь с Android-речевым API

EDIT: Я должен был упомянуть об этом уже, но я запускаю этот код в службе. Все приложение включено/выключено кнопкой виджета и не имеет активности.


Обновление: я попытался подключить источники SDK к проекту, чтобы я мог получить более точное представление о том, где произошел сбой, но из внешний вид, включены только общедоступные API, что, по-видимому, делает их намного менее полезными... может ли кто-нибудь предложить хотя бы отладочный подход для решения этой проблемы? Я как бы застрял.


Я пытаюсь использовать Android пакет распознавания речи для записи речи пользователя и перевода его в текст. К сожалению, когда я пытаюсь инициировать прослушивание, я получаю ошибку ANR, которая не указывает на что-то конкретное.

Как указывает API SpeechRecognizer, генерируется исключение RuntimeException, если вы попытаетесь вызвать его из основного потока. Это заставило бы меня задаться вопросом, была ли обработка слишком требовательна... но я знаю, что для этой цели другие приложения используют API Android, и это обычно довольно быстро.

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

Вот (обрезанный) образец кода, который я пытаюсь вызвать из моей службы. Это правильный подход?

Спасибо, что нашли время, чтобы помочь. Это было препятствие, которое я еще не смог преодолеть.

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

Вам не нужно создавать класс SpeechRecognizer самостоятельно, и вам не нужно внедрять RecognizerListener. Google сделал их общедоступными, чтобы они были хорошими, но они выглядят довольно сложными и, вероятно, для использования только экспертами.

Чтобы получить текст от речи пользователей, просто нужно использовать RecognizerIntent.ACTION_RECOGNIZE_SPEECH, чтобы запустить встроенную функцию распознавания речи, а затем дождаться, когда результат вернется в onActivityResult. Взгляните на пример кода здесь:

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

Я вытащил его из этой статьи.

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

Удачи.

Ответ 2

Обязательно используйте разрешение RECORD_AUDIO.

Ответ 3

Из службы вы должны создать распознаватель из петлителя, работающего в основном потоке. Также RecognizerIntent.EXTRA_RESULTS должен быть SpeechRecognizer.RESULTS_RECOGNITION.

код psuedo:

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

Вместо getApplicationContext() используйте this (т.е. ваш экземпляр службы). android.app.Service наследуется от контекста.

Ответ 5

Вот проблема, с которой я столкнулся, которая может быть связана с вашей. Я получал нуль, независимо от того, из этой строки:

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

Изменение этого параметра полностью устраняет проблему:

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

Я распечатал набор из набора, и это было единственное значение. Обратите внимание, что значение "results_recognition" не является значением строки, хранящейся в RecognizerIntent.EXTRA_RESULTS. Я думаю, что ошибка или, по крайней мере, это должно быть, поскольку использование RecognizerIntent.EXTRA_RESULTS отлично работает в режиме Activity для распознавания речи, но не тогда, когда кто-то использует SpeechRecognizer.

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

Ответ 6

У меня это получилось, установив приложение Google Voice