Android应用内持续语音识别模块实现问题求助
解决方案:应用内持续语音识别(Java/Kotlin)
核心思路
要实现应用前台时持续监听,核心是绑定Activity生命周期,同时避免直接在onSpeechEnded()中立即重启监听——这会导致SpeechRecognizer状态异常,出现识别失效的情况。正确的做法是在识别完成(成功/失败)后,通过延迟重启来保证识别器状态正常。
Java 实现示例
import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.speech.RecognitionListener; import android.speech.RecognizerIntent; import android.speech.SpeechRecognizer; import android.util.Log; import java.util.List; public class MainActivity extends Activity { private SpeechRecognizer speechRecognizer; private Intent recognizerIntent; private Handler handler = new Handler(); private static final long RESTART_LISTEN_DELAY = 500; // 延迟500ms重启,避免状态冲突 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化语音识别器 speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this); recognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); recognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getPackageName()); speechRecognizer.setRecognitionListener(new RecognitionListener() { @Override public void onReadyForSpeech(Bundle params) {} @Override public void onBeginningOfSpeech() {} @Override public void onRmsChanged(float rmsdB) {} @Override public void onBufferReceived(byte[] buffer) {} @Override public void onEndOfSpeech() {} @Override public void onError(int error) { Log.e("SpeechRecog", "Error code: " + error); // 错误后重启监听 restartListening(); } @Override public void onResults(Bundle results) { List<String> matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); if (matches != null && !matches.isEmpty()) { String voiceText = matches.get(0); // 处理识别到的文本 Log.d("SpeechRecog", "识别结果: " + voiceText); } // 识别完成后重启监听 restartListening(); } @Override public void onPartialResults(Bundle partialResults) {} @Override public void onEvent(int eventType, Bundle params) {} }); } @Override protected void onResume() { super.onResume(); // 回到前台时启动监听 startListeningSafely(); } @Override protected void onPause() { super.onPause(); // 退到后台时停止监听并释放资源 stopListening(); } @Override protected void onDestroy() { super.onDestroy(); if (speechRecognizer != null) { speechRecognizer.destroy(); } } private void startListeningSafely() { if (speechRecognizer != null && !speechRecognizer.isListening()) { speechRecognizer.startListening(recognizerIntent); } } private void stopListening() { if (speechRecognizer != null && speechRecognizer.isListening()) { speechRecognizer.stopListening(); } } private void restartListening() { // 先停止当前监听,再延迟重启 stopListening(); handler.postDelayed(this::startListeningSafely, RESTART_LISTEN_DELAY); } }
Kotlin 实现示例
如果切换到Kotlin,代码会更简洁,核心逻辑和Java一致:
import android.app.Activity import android.content.Intent import android.os.Bundle import android.os.Handler import android.speech.RecognitionListener import android.speech.RecognizerIntent import android.speech.SpeechRecognizer import android.util.Log class MainActivity : Activity() { private lateinit var speechRecognizer: SpeechRecognizer private lateinit var recognizerIntent: Intent private val handler = Handler() private val RESTART_LISTEN_DELAY = 500L override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this) recognizerIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM) putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, packageName) } speechRecognizer.setRecognitionListener(object : RecognitionListener { override fun onReadyForSpeech(params: Bundle?) {} override fun onBeginningOfSpeech() {} override fun onRmsChanged(rmsdB: Float) {} override fun onBufferReceived(buffer: ByteArray?) {} override fun onEndOfSpeech() {} override fun onError(error: Int) { Log.e("SpeechRecog", "Error code: $error") restartListening() } override fun onResults(results: Bundle?) { results?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)?.let { matches -> if (matches.isNotEmpty()) { val voiceText = matches[0] Log.d("SpeechRecog", "识别结果: $voiceText") } } restartListening() } override fun onPartialResults(partialResults: Bundle?) {} override fun onEvent(eventType: Int, params: Bundle?) {} }) } override fun onResume() { super.onResume() startListeningSafely() } override fun onPause() { super.onPause() stopListening() } override fun onDestroy() { super.onDestroy() speechRecognizer.destroy() } private fun startListeningSafely() { if (!speechRecognizer.isListening) { speechRecognizer.startListening(recognizerIntent) } } private fun stopListening() { if (speechRecognizer.isListening) { speechRecognizer.stopListening() } } private fun restartListening() { stopListening() handler.postDelayed({ startListeningSafely() }, RESTART_LISTEN_DELAY) } }
关键注意事项
- 生命周期绑定:在
onResume启动、onPause停止,确保只有应用前台时运行,避免后台资源浪费或被系统限制。 - 延迟重启:添加500ms延迟是为了让SpeechRecognizer完成状态重置,避免连续调用
startListening导致的状态异常(这就是你之前失效的主要原因)。 - 错误处理:所有错误场景都要重启监听,防止因识别超时、无语音输入等情况导致监听中断。
- 权限申请:别忘了在Manifest中添加
android.permission.RECORD_AUDIO权限,并且在运行时动态申请(Android 6.0+)。
内容的提问来源于stack exchange,提问作者Michal.K
相关产品推荐
相关产品推荐

