Android 14持续语音识别运行3-4小时后异常终止问题排查
我在Android 14上实现了连续语音识别,代码如下:
public async Task<string> Listen(CultureInfo culture, IProgress<string> recognitionResult, CancellationToken cancellationToken) { try { var taskResult = new TaskCompletionSource<string>(); listener = new SpeechRecognitionListener { Error = ex => { taskResult.TrySetException(new Exception("Failure in speech engine - " + ex)); }, PartialResults = sentence => { recognitionResult?.Report(sentence); }, Results = sentence => taskResult.TrySetResult(sentence) }; speechRecognizer = SpeechRecognizer.CreateSpeechRecognizer(Android.App.Application.Context, new ComponentName( "com.google.android.tts", "com.google.android.apps.speech.tts.googletts.service.GoogleTTSRecognitionService" )); if (speechRecognizer is null) { throw new ArgumentException("Speech recognizer is not available"); } speechRecognizer.SetRecognitionListener(listener); speechRecognizer.StartListening(CreateSpeechIntent(culture)); await using (cancellationToken.Register(() => { StopRecording(); taskResult.TrySetCanceled(); })) { return await taskResult.Task; } } catch (Exception ex) { throw; } finally { StopRecording(); } } private void StopRecording() { if (speechRecognizer != null) { speechRecognizer?.StopListening(); speechRecognizer?.Destroy(); speechRecognizer = null; } } private Android.Content.Intent CreateSpeechIntent(CultureInfo culture) { var intent = new Android.Content.Intent(RecognizerIntent.ActionRecognizeSpeech); string language = culture.Name; var javaLocale = Java.Util.Locale.ForLanguageTag(language).ToString(); intent.PutExtra(RecognizerIntent.ExtraLanguage, javaLocale); intent.PutExtra(RecognizerIntent.ExtraLanguagePreference, javaLocale); intent.PutExtra(RecognizerIntent.ExtraLanguageModel, RecognizerIntent.LanguageModelFreeForm); intent.PutExtra(RecognizerIntent.ExtraCallingPackage, Android.App.Application.Context.PackageName); intent.PutExtra(RecognizerIntent.ExtraOnlyReturnLanguagePreference, true); intent.PutExtra(RecognizerIntent.ExtraMaxResults, 1); intent.PutExtra(RecognizerIntent.ExtraPartialResults, false); return intent; }
程序正常运行3-4小时后,识别会随机停止,麦克风图标消失,对应的错误日志如下:
2024-09-08 04:18:13.199 1382-1382 ActivityManager system_server W bindService exceeded max service connection number per process, callerApp:system intent:Intent { act=android.speech.RecognitionService cmp=com.google.android.tts/com.google.android.apps.speech.tts.googletts.service.GoogleTTSRecognitionService }
停止并重启谷歌语音识别与合成服务,再重启应用后可恢复正常。请问:
- 进程的最大服务连接数是多少?
- 该问题为何出现?
- 我的代码存在哪些问题?
解答
1. 进程的最大服务连接数
Android系统中,单个进程对同一服务的默认最大绑定连接数为100个,该数值定义在系统源码ActivityManagerService的MAX_SERVICE_CONNECTIONS_PER_PROCESS常量中。
2. 问题出现的原因
日志提示的错误说明,系统进程或应用进程与谷歌语音识别服务建立的绑定连接数超过了上限。每次创建SpeechRecognizer实例都会发起一次服务绑定,即便调用Destroy(),也可能存在连接未被系统及时回收的情况,长时间重复创建销毁操作后,连接数累积达到上限,导致无法再建立新的服务连接,最终语音识别服务无法正常启动。
3. 代码存在的问题
- 重复创建SpeechRecognizer实例:每次调用
Listen方法都会新建SpeechRecognizer实例,虽然在finally块中销毁实例,但异步场景下可能存在资源泄漏,且频繁创建销毁会不断产生新的服务绑定连接,加速触发连接数上限。 - 连续识别逻辑错误:当前代码是单次识别逻辑(通过
TaskCompletionSource等待单次结果),并非真正的连续识别。每次识别完成就销毁实例,后续继续识别又重新创建,这种频繁操作必然导致绑定连接累积。 - Intent参数设置不合理:
- 设置
ExtraOnlyReturnLanguagePreference = true会让识别服务仅返回语言偏好,而非实际识别结果,可能导致识别流程异常,加剧连接泄漏; ExtraPartialResults = false关闭了部分识别结果反馈,不符合连续识别的实时需求,也可能让识别服务的连接生命周期出现异常。
- 设置
内容的提问来源于stack exchange,提问作者Oxana b

