SpeechRecognizer 导致 ANR...我需要有关 Android 语音 API 的帮助

Posted

技术标签:

【中文标题】SpeechRecognizer 导致 ANR...我需要有关 Android 语音 API 的帮助【英文标题】:SpeechRecognizer causes ANR... I need help with Android speech API 【发布时间】:2011-06-01 09:20:51 【问题描述】:

编辑:我应该已经提到了这一点,但我正在服务中运行此代码。整个应用由一个小部件按钮打开/关闭,并且没有任何活动。


更新:我尝试将 SDK 源附加到项目中,以便更准确地了解故障发生的位置,但从 the looks of it 开始,仅包含公共 API,这似乎使它们变得不那么有用...任何人都可以建议至少一种调试方法来解决此问题吗?我有点卡住了。


我正在尝试使用 android 的 speech recognition package 记录用户语音并将其翻译成文本。不幸的是,当我尝试启动监听时,我收到了一个 ANR 错误,它没有指向任何特定的内容。

正如 SpeechRecognizer API 所指出的,如果您尝试从主线程调用 RuntimeException,则会引发 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);

【问题讨论】:

软件开发标签有点多余 ;-) 这更适用于讨论该领域的主题。 【参考方案1】:

确保使用 RECORD_AUDIO 权限。

【讨论】:

【参考方案2】:

您不需要自己创建 SpeechRecognizer 类,也不需要实现 RecognizerListener。 Google 将它们公开是为了很好,但它们看起来很复杂,可能仅供专家使用。

要从用户语音中获取文本,您只需使用 RecognizerIntent.ACTION_RECOGNIZE_SPEECH 启动内置语音识别器 Activity,然后在 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

祝你好运。

【讨论】:

这就是我开始的道路。我选择了 SpeechRecognizer 方法,因为我在 Service 的幕后运行所有内容……如果我的应用程序没有焦点(它在后台运行),启动 Activity 似乎不正确。如果归根结底,我可能不得不使用一个活动。我的应用程序旨在无需用户在屏幕上进行交互即可使用。 从我目前所读到的内容来看,语音识别 API 只是一个接口,它的实现实际上存在于其他地方,例如“语音搜索”应用程序。我相信它是基于专有技术而不是开源的。看起来您受制于所提供的界面。 这听起来对我来说是正确的,但我认为我的代码中存在某种设计缺陷,因为我的意图应该由与广播我的意图相同的应用程序/活动来处理使用 startActivityForResult()。实现应该同样影响这两种技术......我想我可能会选择一个活动作为替代解决方案。【参考方案3】:

从服务中,您必须从在主线程上运行的 looper 创建识别器。此外,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);

【讨论】:

【参考方案4】:

使用this(即您的服务实例)代替getApplicationContext()android.app.Service 继承自 Context。

【讨论】:

【参考方案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 时就不行。

无论如何,我很可能不会再查看此网站,但如果您有任何问题,请给我发电子邮件,因为我现在确实可以在没有任何提示、哔哔声或其他任何东西的情况下进行语音识别。

【讨论】:

你需要这个:recognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, "Your.package"); identifyrIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true); 使用 getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION) 代替硬编码字符串【参考方案6】:

我通过安装 Google Voice 应用程序来实现这一点

【讨论】:

以上是关于SpeechRecognizer 导致 ANR...我需要有关 Android 语音 API 的帮助的主要内容,如果未能解决你的问题,请参考以下文章

Android 进阶——性能优化之因Handler引起句柄泄漏导致ANR的定位和解决

Android 进阶——性能优化之因Handler引起句柄泄漏导致ANR的定位和解决

Android 进阶——性能优化之因Handler引起句柄泄漏导致ANR的定位和解决

为什么“15。。。”会导致微信ANR?

为什么“15。。。”会导致微信ANR?

Android项目中多次操作SharedPreferences导致ANR场景的解决