无法通过MediaRecorder.AudioSource.MIC录制通话,调用start后停止的问题
解决MediaRecorder调用start()后立即停止的通话录制问题
我来帮你梳理下这个问题的常见原因和解决思路,这种调用recorder.start()就停止的情况在通话录音场景里挺普遍的,咱们一步步排查:
1. 权限问题(最常见)
Android对录音和通话相关权限的限制非常严格,尤其是高版本系统:
- 首先确保清单文件里声明了必要权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 如果存储到外部目录 -->
- Android 6.0+需要动态申请权限,而且RECORD_AUDIO是危险权限,必须在Activity里主动请求,Service里无法直接触发权限弹窗。建议在APP启动时就完成权限申请,否则录制时会直接失败。
- 注意:Android 10及以上,系统会优先占用MIC资源用于通话,第三方APP很难通过
MIC源录制通话内容,部分定制系统甚至会直接拦截这种请求。
2. MediaRecorder配置顺序与完整性
MediaRecorder的配置有严格的顺序要求,而且你提供的代码里只写到了setAudioEncoder,后面的关键步骤可能缺失:
正确的配置流程应该是:
private void startRecording() throws IOException { if (!isRecording) { this.isRecording = true; recorder = new MediaRecorder(); // 别忘了初始化实例! recorder.setAudioSource(MediaRecorder.AudioSource.MIC); recorder.setAudioSamplingRate(8000); recorder.setAudioEncodingBitRate(12200); recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 必须设置输出文件路径(建议用应用私有目录,避免权限问题) File outputFile = new File(getExternalFilesDir(null), "call_recording.3gp"); recorder.setOutputFile(outputFile.getAbsolutePath()); recorder.prepare(); // 这一步绝对不能少! recorder.start(); } }
如果跳过prepare()直接调用start(),MediaRecorder会立即崩溃停止,这是很多新手容易踩的坑。
3. Service生命周期被系统回收
你的录制逻辑在Service里,而通话过程中系统可能会因为资源紧张杀掉后台Service,导致录制中断:
- Android 8.0+要求后台Service必须升级为前台服务,否则启动后5秒内会被系统杀死。你需要在Service里启动前台通知:
private static final String CHANNEL_ID = "call_recording_channel"; @Override public void onCreate() { super.onCreate(); // 创建通知渠道(Android 8.0+必备) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "通话录制", NotificationManager.IMPORTANCE_LOW); NotificationManager manager = getSystemService(NotificationManager.class); manager.createNotificationChannel(channel); } // 启动前台服务 Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("通话录制中") .setContentText("正在录制通话音频") .setSmallIcon(R.drawable.ic_recording) .build(); startForeground(1, notification); }
4. 音频焦点冲突
通话时系统会独占音频焦点,你的MediaRecorder请求MIC资源会被系统拒绝:
可以尝试通过AudioManager请求音频焦点,虽然不一定能成功,但值得一试:
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); int focusResult = audioManager.requestAudioFocus( null, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT ); if (focusResult != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { // 焦点获取失败,无法录制 return; }
另外,注意:MediaRecorder.AudioSource.VOICE_CALL这个源理论上可以录制通话双方的声音,但这个权限只有系统APP才能获取,普通第三方APP无法使用。
5. 状态管理问题
确保isRecording的状态逻辑正确,避免重复调用start():
- 在
stopRecording()里要正确释放资源并重置状态:
private void stopRecording() { if (isRecording && recorder != null) { isRecording = false; try { recorder.stop(); } catch (RuntimeException e) { // 处理录制未正常启动的情况 e.printStackTrace(); } recorder.release(); recorder = null; } }
- 在Service的
onDestroy()方法里也要调用stopRecording(),防止资源泄漏。
内容的提问来源于stack exchange,提问作者M Talha




