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

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+的麦克风权限要求,前台服务必须在收到客户端的识别请求、权限校验通过后再启动,修改对应代码:

  1. 移除onCreate中的startForeground调用
  2. 调整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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 16:57:04