Android11下自定义RecognitionService提示无RECORD_AUDIO权限问题求助
问题修复方案
核心原因说明
你遇到的报错本质是权限校验的对象不匹配:PermissionChecker.checkCallingPermissionForDataDelivery 校验的是**发起识别请求的客户端(你的MainActivity所在进程)**的录音权限,而非RecognitionService自身的权限,你之前用ContextCompat.checkSelfPermission校验的是服务自身的权限,二者校验对象完全不同,所以会出现权限已授予仍然报错的情况。
具体修复步骤
1. 显式重写RecognitionService的权限校验方法
你需要在SampleSpeechRecognizerService中显式重写checkPermissions方法,传入调用方的真实包名进行校验:
@Override protected boolean checkPermissions() { String callingPackage = getCallingPackage(); if (callingPackage == null) { return false; } return PermissionChecker.checkCallingPermissionForDataDelivery(this, Manifest.permission.RECORD_AUDIO, callingPackage, null, null) == PermissionChecker.PERMISSION_GRANTED; }
2. 修正前台服务的启动时机
你当前在Service的onCreate方法就启动前台服务不符合Android 11+的麦克风权限要求,前台服务必须在收到客户端的识别请求、权限校验通过后再启动,修改对应代码:
- 移除
onCreate中的startForeground调用 - 调整
onStartListening逻辑:
@Override protected void onStartListening(Intent recognizerIntent, Callback listener) { // 先校验权限,校验失败直接返回权限错误 if (!checkPermissions()) { try { listener.error(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS); } catch (RemoteException e) { e.printStackTrace(); } return; } // 校验通过后再启动前台服务 Notification notification = new Notification.Builder(this, CHANNEL_ID) .setContentTitle("语音识别服务") .setContentText("正在进行语音转文字") .setSmallIcon(R.drawable.ic_android) .build(); startForeground(1, notification); // 保留原有逻辑 mListener = listener; Log.i("Sample", "onStartListening"); mExtras = recognizerIntent.getExtras(); if (mExtras == null) { mExtras = new Bundle(); } onReadyForSpeech(new Bundle()); onBeginningOfSpeech(); }
3. 修正识别服务的绑定逻辑
你当前遍历ResolveInfo的逻辑可能会优先拿到系统默认的谷歌识别服务,建议直接指定绑定自己实现的服务:
private void configureSpeechListener() { // 直接指定自定义的识别服务组件 ComponentName currentRecognitionCmp = new ComponentName(this, SampleSpeechRecognizerService.class); speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this, currentRecognitionCmp); // 保留原有逻辑 speechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault()); speechRecognizer.setRecognitionListener(new SampleSpeechRecognitionListener()); }
4. 额外注意事项
Android 11及以上系统中,应用退到后台时麦克风权限会被系统临时收回,发起语音识别请求时需要确保应用处于前台,否则也会触发权限不足报错。
内容的提问来源于stack exchange,提问作者Renil Joy
相关产品推荐
相关产品推荐

