SpeechRecognizer вызывает ANR... Мне нужна помощь с Android API речи
РЕДАКТИРОВАТЬ: я должен был уже упомянуть об этом, но я запускаю этот код в службе. Все приложение включается / выключается кнопкой виджета и не имеет активности.
Обновление: я попытался подключить источники SDK к проекту, чтобы получить более точное представление о том, где произошел сбой, но, судя по всему, включены только общедоступные API, что, по-видимому, делает их намного менее полезными. Кто-нибудь может предложить хотя бы отладочный подход для решения этой проблемы? Я немного застрял.
Я пытаюсь использовать пакет распознавания речи Android для записи речи пользователя и перевода ее в текст. К сожалению, когда я пытаюсь инициировать прослушивание, я получаю ошибку ANR, которая не указывает ни на что конкретное.
Как указывает API-интерфейс SpeechRecognizer, выдается исключение 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);
6 ответов
Из службы вы должны создать распознаватель из петлителя, работающего в основном потоке. Также 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);
Вам не нужно создавать класс SpeechRecognizer самостоятельно, а также не нужно реализовывать RecognizerListener. Google сделал их публичными, чтобы быть хорошими, но они выглядят довольно сложными и, вероятно, для использования только экспертами.
Чтобы получить текст из речи пользователя, вам просто нужно использовать RecognizerIntent.ACTION_RECOGNIZE_SPEECH для запуска встроенного распознавателя речи Activity, а затем дождаться возвращения результата в onActivityResult. Посмотрите на пример кода здесь:
Я вытащил это из этой статьи.
http://developer.android.com/resources/articles/speech-input.html
Удачи.
Вместо getApplicationContext()
использовать this
(т.е. ваш экземпляр службы). android.app.Service
наследует от контекста.
Вот проблема, с которой я столкнулся, которая может быть связана с вашей. Я получал ноль, несмотря ни на что, из этой строки:
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.
В любом случае, я, скорее всего, больше не буду проверять этот веб-сайт, но, пожалуйста, напишите мне, если у вас есть какие-либо вопросы, поскольку у меня теперь распознавание речи работает без каких-либо подсказок, звуковых сигналов или чего-либо еще.