You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现永久运行仅响应“OK app”的Android SpeechRecognizer

Android 永久语音唤醒功能实现方案

问题根因

原生SpeechRecognizer本身定位为短语音识别组件,默认检测到2秒左右静默、或识别完成就会自动结束监听。你当前实现中每次识别结束都销毁并重建SpeechRecognizer实例,这段重建耗时就是识别空白期,自然会出现唤醒词漏响应的问题。

优化方案

方案1:优化现有SpeechRecognizer实现(快速修复,适合测试)

  • 复用SpeechRecognizer实例,不要每次结果/错误回调就销毁重建,仅重启监听即可,大幅降低空白期时长
  • 调整识别参数,延长静默超时阈值,开启部分结果回调,无需等语音完全结束即可检测唤醒词
  • 补全错误回调的重启逻辑,除了错误码7(无匹配结果)外,静默超时、识别器繁忙等可恢复错误都要触发重启监听
  • 将服务改为前台服务,Android 8.0+后台服务会被系统自动回收,必须展示常驻通知保证服务存活,同时申请录音权限、后台麦克风权限、忽略电池优化权限。

方案2:改用专业唤醒词引擎(生产环境推荐)

全量语音识别做永久监听功耗高、准确率低,生产环境建议使用专门的唤醒词方案:

  • Android 12及以上可使用系统自带AlwaysOnHotwordDetector,系统级低功耗永久唤醒,无识别间隙,不需要自行维护后台服务
  • 低版本可集成离线唤醒SDK,比如开源的Porcupine、PocketSphinx,或国内百度、科大讯飞的离线唤醒组件,仅监听你设置的"OK app"关键词,命中后再拉起全量语音识别做后续交互,功耗和准确率远高于原生SpeechRecognizer实现。

优化后核心代码示例

public class SttService extends Service implements RecognitionListener {
    private static final String TAG = "SstService";
    SpeechRecognizer mSpeech;

    // 初始化一次实例,复用
    private void initSpeechRecognizer() {
        if (mSpeech == null) {
            mSpeech = SpeechRecognizer.createSpeechRecognizer(SttService.this);
            mSpeech.setRecognitionListener(SttService.this);
        }
    }

    private void startListening() {
        Intent intent1 = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        intent1.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "en");
        // 开启部分结果回调,提前检测唤醒词
        intent1.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true);
        // 静默超时改为5秒
        intent1.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, 5000);
        // 最小语音长度设为1秒
        intent1.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 1000);
        mSpeech.startListening(intent1);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand: I am running");
        // 改成前台服务,这里需要自行添加通知创建逻辑
        // startForeground(NOTIFICATION_ID, notification);
        initSpeechRecognizer();
        startListening();
        return START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    // 其他默认回调省略...

    @Override
    public void onError(int error) {
        Log.e(TAG, "onError: " + error);
        // 所有可恢复错误都触发重启
        if (error == SpeechRecognizer.ERROR_NO_MATCH 
            || error == SpeechRecognizer.ERROR_SPEECH_TIMEOUT
            || error == SpeechRecognizer.ERROR_RECOGNIZER_BUSY) {
            startListening();
        }
    }

    @Override
    public void onPartialResults(Bundle partialResults) {
        ArrayList<String> partials = partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
        if (partials != null && !partials.isEmpty()) {
            for (String text : partials) {
                if (text.equalsIgnoreCase("OK app")) {
                    // 提前命中唤醒词,执行对应逻辑
                    Log.e(TAG, "唤醒成功:" + text);
                    return;
                }
            }
        }
    }

    @Override
    public void onResults(Bundle results) {
        ArrayList<String> resultsStringArrayList = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
        if (resultsStringArrayList == null || resultsStringArrayList.isEmpty()) {
            startListening();
            return;
        }
        String mainResult = resultsStringArrayList.get(0);
        Log.e(TAG, "onResults: " + mainResult);
        if (mainResult.equalsIgnoreCase("OK app")) {
            System.out.println("What's up?");
        }
        // 直接重启监听,不销毁实例
        startListening();
    }
}

内容的提问来源于stack exchange,提问作者xRay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 19:24:07