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

MediaRecorder启动失败错误码-2147483648,通话录音问题求助

解决MediaRecorder: start failed : -2147483648通话录音错误

这个错误我之前帮不少Android开发者排查过,核心原因大多和系统权限限制以及Android版本对通话录音API的严格管控有关,咱们一步步拆解问题,再给出可行的解决方案:

为什么会出现start failed : -2147483648?

这个错误码对应的是MediaRecorder的非法操作异常,根源在于你使用的MediaRecorder.AudioSource.VOICE_CALL音频源:

  • 从Android 10(API 29)开始,Google直接封锁了普通应用调用VOICE_CALL的权限,只有系统级应用才能使用这个接口;
  • 就算是Android 10以下的版本,很多国内厂商也早就通过定制系统限制了这个接口的调用,防止隐私泄露。

这就是你调用recorder.start()时直接失败的核心原因。

为什么用VOICE_COMMUNICATION录不到来电者声音?

VOICE_COMMUNICATION是为语音通话场景优化的音频源,但它的设计逻辑是只采集当前设备麦克风的输入,不会捕获对方通过通话链路传输过来的音频,所以自然录不到来电者的声音。

可行的解决方案

1. 适配Android 10+的官方规则

从Android 10开始,普通应用想要录制通话,只能通过MediaProjection API实现——这个API原本是用于屏幕录制,但同时会捕获系统的所有音频(包括通话)。不过这种方式需要用户手动授权"录制屏幕和音频",体验上需要引导用户操作:

  • 先申请RECORD_AUDIO、WRITE_EXTERNAL_STORAGE(Android 13+还要POST_NOTIFICATIONS)权限;
  • 启动MediaProjectionManager获取用户授权;
  • 通过MediaProjection创建VirtualDisplay,同时录制系统音频。

2. 低版本设备的折中方案(Android 9及以下)

如果你的应用目标用户主要是低版本设备,可以尝试:

  • 切换音频源为MediaRecorder.AudioSource.MIC;
  • 引导用户开启通话免提,让麦克风直接采集通话声音;
  • 这种方式体验一般,但至少能实现录音功能,缺点是依赖免提,音质受环境影响。

3. 检查并完善权限配置

不管用哪种方案,都必须确保权限配置正确:
在AndroidManifest.xml中声明必要权限:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Android 10+ 访问媒体文件需要 -->
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<!-- Android 12+ 通知权限 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

而且这些都是危险权限,必须在运行时动态申请,不能只靠Manifest声明。

优化你的代码示例

针对你的代码,我调整了权限检查、音频源适配和文件创建逻辑,避免一些潜在问题:

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class CallRecorder {
    private MediaRecorder recorder;
    private boolean recordstarted = false;
    private Context context;

    public CallRecorder(Context context) {
        this.context = context;
    }

    public void SesKayitBaslat(String number) {
        Toast.makeText(context, "ANSWERED", Toast.LENGTH_LONG).show();
        String timeStamp = new SimpleDateFormat("dd-MM-yyyy hh-mm-ss", Locale.getDefault()).format(new Date());
        File sampleDir = new File(Environment.getExternalStorageDirectory(), "/ASesKaydi");
        
        if (!sampleDir.exists()) {
            sampleDir.mkdirs();
        }
        
        String fileName = "Record_" + timeStamp + ".amr";
        File audioFile = new File(sampleDir, fileName);

        // 先检查权限,没有权限就申请
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions((Activity) context,
                    new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    1001);
            Toast.makeText(context, "请授予录音和存储权限", Toast.LENGTH_SHORT).show();
            return;
        }

        recorder = new MediaRecorder();
        // 根据系统版本选择合适的音频源
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        } else {
            recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
        }
        
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        recorder.setOutputFile(audioFile.getAbsolutePath());

        try {
            recorder.prepare();
            if (!recordstarted) {
                recorder.start();
                recordstarted = true;
                Toast.makeText(context, "录音已开始", Toast.LENGTH_SHORT).show();
            }
        } catch (IllegalStateException e) {
            Toast.makeText(context, "录音启动失败:状态异常", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        } catch (IOException e) {
            Toast.makeText(context, "录音启动失败:IO异常", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
    }

    // 记得添加停止录音的方法
    public void SesKayitDurdur() {
        if (recordstarted && recorder != null) {
            try {
                recorder.stop();
                recorder.release();
                recordstarted = false;
                Toast.makeText(context, "录音已停止", Toast.LENGTH_SHORT).show();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
        }
    }
}

最后提醒

Android平台对通话录音的限制越来越严格,主要是为了保护用户隐私。如果你的应用依赖通话录音功能,最好的方式是引导用户使用手机系统自带的通话录音功能;如果必须自己实现,MediaProjection是目前高版本系统唯一合法的路径,但需要用户主动授权。

内容的提问来源于stack exchange,提问作者Zibian Domichi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:47:24