三星Galaxy Watch4上RecognitionListener报无语音识别服务问题咨询
问题定位
报错E/SpeechRecognizer: no selected voice recognition service的核心原因是系统找不到可用的、已配置为默认的语音识别服务实现,结合你给出的代码、配置和Galaxy Watch4(搭载Wear OS 3+)的运行环境,具体触发点如下:
- 代码逻辑错误:连续两次给
speechRecognizer赋值,第一次创建的指定Google识别服务的实例,被下一行createOnDeviceSpeechRecognizer新建的端侧识别实例直接覆盖,你写的指定Google服务的代码完全没有生效,最终调用的是依赖系统默认配置的端侧识别接口。 - 设备环境限制:Galaxy Watch4不同发售版本的默认语音服务不一样,国行版本默认是三星Bixby,不支持标准
SpeechRecognizer的离线调用接口;就算是国际版预装了Google服务,默认也可能没有把Google语音识别设为系统默认语音服务,端侧识别接口直接调用会失败。 - 配置缺失:Manifest里没有声明麦克风权限、前台服务类型,代码里
startForeground传参错误,没有做识别服务可用性的前置校验,也没有动态申请运行时权限。
修复步骤
1. 修正初始化逻辑
不要重复赋值覆盖识别实例,二选一初始化即可,初始化前必须做可用性校验:
// 通知ID可自定义全局常量 private const val FOREGROUND_NOTI_ID = 1001 override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { // 二选一:要么用指定的Google识别服务,要么用端侧离线识别,不要同时初始化 // 选项A:使用端侧离线识别 if (!SpeechRecognizer.isOnDeviceRecognitionAvailable(this)) { Log.e("SpeechErr", "当前设备不支持端侧离线识别,请检查Google服务版本") stopSelf() return START_NOT_STICKY } speechRecognizer = SpeechRecognizer.createOnDeviceSpeechRecognizer(this) // 选项B:强制指定Google语音识别服务 // val recogComponent = ComponentName.unflattenFromString("com.google.android.googlequicksearchbox/com.google.android.voicesearch.serviceapi.GoogleRecognitionService") // val serviceAvailable = try { // packageManager.getServiceInfo(recogComponent, PackageManager.GET_META_DATA) // true // } catch (e: Exception) { // false // } // speechRecognizer = if (serviceAvailable) { // SpeechRecognizer.createSpeechRecognizer(this, recogComponent) // } else { // SpeechRecognizer.createSpeechRecognizer(this) // } speechRecognizer.setRecognitionListener(this) val recogIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault()) putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM) putExtra(RecognizerIntent.EXTRA_PREFER_OFFLINE, true) putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, 3000) } // 注意:startForeground第一个参数是通知ID,第二个是Notification实例,你原来传this是错误用法 startForeground(FOREGROUND_NOTI_ID, buildForegroundNotification()) speechRecognizer.startListening(recogIntent) return START_STICKY } // 构建前台服务通知,Wear OS通知建议设为低重要性,避免弹出横幅干扰 private fun buildForegroundNotification(): Notification { val channel = NotificationChannel("speech_listen", "语音监听", NotificationManager.IMPORTANCE_LOW) val manager = getSystemService(NotificationManager::class.java) manager.createNotificationChannel(channel) return NotificationCompat.Builder(this, "speech_listen") .setContentTitle("语音服务运行中") .setSmallIcon(R.drawable.ic_mic) .build() }
2. 补全Manifest配置与权限
Wear OS对麦克风、前台服务管控极严,必须补全以下配置,你现有的配置缺少核心权限和服务声明:
<!-- 必要权限 --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" /> <!-- Android13+需要通知权限才能显示前台服务通知 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <application ...> <!-- 声明语音监听服务,指定foregroundServiceType为microphone --> <service android:name=".SpeechListener" android:exported="false" android:foregroundServiceType="microphone" /> </application> <!-- 原有queries配置保留即可 --> <queries> <package android:name="com.google.android.googlequicksearchbox"/> <intent> <action android:name="android.speech.RecognitionService" /> </intent> </queries>
注意:RECORD_AUDIO、POST_NOTIFICATIONS都是运行时权限,必须在MainActivity里动态申请,拿到用户授权之后再启动SpeechListener服务,否则服务拿不到麦克风权限,识别会直接失败。
3. Galaxy Watch4专属适配
- 打开手表设置-应用-默认应用-语音输入,确认默认语音服务设置为Google语音识别,如果默认是Bixby,Bixby不开放标准SpeechRecognizer接口,会直接报你遇到的错误。
- 如果使用离线识别,需要先将手表和手机正常配对,在Google助理设置页下载对应语言的离线语音包,手表端不会自动下载离线包,没有对应语言包时端侧识别无法启动。
- 确认手表Google Play服务版本不低于21.xx,低版本Google服务不支持
createOnDeviceSpeechRecognizer接口。 - 测试时关闭省电模式、后台活动限制,Wear OS在省电模式下会禁用非系统级语音服务。
4. 补全错误回调
你目前只实现了onResults回调,必须补全onError回调拿到具体错误码,不要只依赖系统日志排查问题:
override fun onError(error: Int) { val errorText = when(error) { SpeechRecognizer.ERROR_AUDIO -> "音频采集错误" SpeechRecognizer.ERROR_CLIENT -> "客户端调用错误" SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> "缺少必要权限" SpeechRecognizer.ERROR_NETWORK -> "网络连接错误" SpeechRecognizer.ERROR_NO_MATCH -> "未识别到有效语音" SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> "识别服务被占用" SpeechRecognizer.ERROR_SERVER -> "识别服务端错误" SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> "未检测到语音输入" else -> "未知错误,码值:$error" } Log.e("SpeechListener", "识别失败:$errorText") }
内容的提问来源于stack exchange,提问作者Sustav
相关产品推荐
相关产品推荐

