SpeechRecognizer вызывает ошибку ANR. Мне нужна помощь с голосовым API Android.

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


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


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

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

java.lang.RuntimeException: SpeechRecognizer should be used only from the application's 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);

person tnunamak    schedule 30.12.2010    source источник
comment
Тег разработки программного обеспечения является избыточным ;-) Это больше для тем, говорящих об этой области в целом.   -  person SapphireSun    schedule 30.12.2010


Ответы (6)


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

person Curtis Shovan    schedule 29.12.2011

Вам не нужно создавать класс 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

Удачи.

person satur9nine    schedule 03.01.2011
comment
Это была дорога, по которой я пошел. Я пошел с подходом SpeechRecognizer, потому что я запускаю все за кулисами в службе... казалось неправильным запускать действие, если мое приложение не имело фокуса (оно работает в фоновом режиме). Если дойдет до этого, мне, возможно, все равно придется использовать Activity. Мое приложение предназначено для использования без взаимодействия с пользователем на экране. - person tnunamak; 03.01.2011
comment
Из того, что я прочитал до сих пор, API распознавания речи — это просто интерфейс, а реализация на самом деле живет где-то еще, например, в приложении голосового поиска. Я считаю, что он основан на проприетарной технологии и не является открытым исходным кодом. Похоже, вы находитесь во власти предоставленного интерфейса. - person satur9nine; 03.01.2011
comment
Это звучит правильно для меня, но я думаю, что в моем коде есть какой-то недостаток дизайна, потому что мое намерение должно обрабатываться тем же приложением/активностью, которое использовалось бы, если бы я должен был передать свое намерение с помощью startActivityForResult(). Реализация должна одинаково влиять на оба метода... Я думаю, что я, вероятно, просто выберу активность в качестве альтернативного решения. - person tnunamak; 09.01.2011

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

псевдокод:

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);
person Matt Cobb    schedule 17.04.2012

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

person Al.    schedule 06.01.2011

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

  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.

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

person Sina Bahram    schedule 13.04.2011
comment
Вам нужно это: распознаватьIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, Your.package); распознаватьIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true); - person gregm; 30.09.2011
comment
Используйте getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION) вместо жестко закодированной строки - person Matt Cobb; 12.06.2015

Я заставил это работать, установив приложение Google Voice.

person oopscope    schedule 06.05.2011