Android 13中如何在语音通话时播放WAV文件让接收方听到?
解决方案:Android 12-13 通话内音频推送+录音适配
一、权限适配(Android 12+ 强制要求)
Android 12(API 31)对音频相关权限做了细化,通话场景需补充声明以下权限到AndroidManifest.xml:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- Android 12+ 新增,前台服务必须 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
动态申请权限时,需同时请求RECORD_AUDIO和POST_NOTIFICATIONS,因为后台音频操作必须依托前台服务,而前台服务需要通知权限。
二、音频会话与路由配置(解决通话内推送失效)
旧版本的音频路由逻辑在Android 12+被系统限制,需明确绑定通话音频通道:
- 配置通话专属音频属性:
AudioAttributes audioAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) .build();
- 强制切换到通话音频模式:
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); // 切换到通话模式,确保音频流进入通话通道 audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); // 按需开启扬声器,通话场景下默认是听筒,开启后可让双方听到推送音频 audioManager.setSpeakerphoneOn(true);
三、替换MediaPlayer为AudioTrack(解决音量低、无法被麦克风采集问题)
MediaPlayer默认输出到媒体通道,和通话通道相互隔离,导致麦克风无法采集推送的音频。改用AudioTrack直接写入通话音频流:
int sampleRate = 44100; int channelConfig = AudioFormat.CHANNEL_OUT_MONO; int audioFormat = AudioFormat.ENCODING_PCM_16BIT; int bufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat); // 初始化AudioTrack并绑定到通话会话 AudioTrack audioTrack = new AudioTrack(audioAttributes, new AudioFormat.Builder() .setSampleRate(sampleRate) .setEncoding(audioFormat) .setChannelMask(channelConfig) .build(), bufferSize, AudioTrack.MODE_STREAM, AudioManager.AUDIO_SESSION_ID_COMMUNICATION); // 读取音频文件PCM数据并推送(示例) FileInputStream fis = new FileInputStream(new File("/sdcard/test.pcm")); byte[] buffer = new byte[bufferSize]; int readLen; audioTrack.play(); while ((readLen = fis.read(buffer)) != -1) { audioTrack.write(buffer, 0, readLen); } audioTrack.stop(); audioTrack.release();
注:如果你的音频文件是MP3等压缩格式,需要先解码为PCM数据再写入AudioTrack。
四、录音功能适配(Android 12+)
录音需绑定到同一通话音频会话,才能采集到通话+推送的混合音频:
int recordBufferSize = AudioRecord.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_IN_MONO, audioFormat); AudioRecord audioRecord = new AudioRecord.Builder() .setAudioAttributes(new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) .build()) .setAudioFormat(new AudioFormat.Builder() .setSampleRate(sampleRate) .setEncoding(audioFormat) .setChannelMask(AudioFormat.CHANNEL_IN_MONO) .build()) .setBufferSizeInBytes(recordBufferSize * 2) .build(); audioRecord.startRecording(); // 读取录音数据并保存逻辑(略)
五、核心注意事项
- 所有音频操作必须放在前台服务中执行:Android 12+ 严格限制后台应用访问音频资源,需启动前台服务并显示通知。
- 共享音频会话ID:推送音频和录音必须使用
AudioManager.AUDIO_SESSION_ID_COMMUNICATION,避免系统隔离音频流。 - 真机测试:模拟器的通话音频路由逻辑和真机差异较大,务必用物理设备测试。
内容的提问来源于stack exchange,提问作者Sumit Chauhan
相关产品推荐
相关产品推荐

