在 Android 中实现通话录音

在 Android 中实现通话录音需要处理系统权限通话状态监听音频录制 等关键步骤。以下是详细实现代码及注释,注意不同 Android 版本和厂商设备的兼容性问题


1. 添加权限声明(AndroidManifest.xml)

复制代码
<!-- 录制音频权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 读取通话状态权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- Android 10+ 需要前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- 存储录音文件权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" 
                 android:maxSdkVersion="28" /> <!-- Android 9及以下需要 -->

2. 创建通话状态监听服务(Java 代码)

复制代码
import android.app.Service;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import java.io.IOException;

public class CallRecordingService extends Service {
    private static final String TAG = "CallRecording";
    private MediaRecorder mediaRecorder;
    private TelephonyManager telephonyManager;
    private PhoneStateListener phoneStateListener;

    @Override
    public void onCreate() {
        super.onCreate();
        // 初始化电话状态监听
        telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        phoneStateListener = new PhoneStateListener() {
            @Override
            public void onCallStateChanged(int state, String phoneNumber) {
                switch (state) {
                    case TelephonyManager.CALL_STATE_OFFHOOK: // 通话开始
                        startRecording(phoneNumber);
                        break;
                    case TelephonyManager.CALL_STATE_IDLE:     // 通话结束
                        stopRecording();
                        break;
                    case TelephonyManager.CALL_STATE_RINGING:  // 来电响铃
                        // 可在此处处理来电号码
                        break;
                }
            }
        };
        // 注册监听器
        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
    }

    /**
     * 开始录音
     */
    private void startRecording(String phoneNumber) {
        try {
            mediaRecorder = new MediaRecorder();
            // 设置音频源(不同设备可能支持不同配置)
            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL); // 需要系统权限
            // 部分设备需改用 MIC(但无法录制对方声音):
            // mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            
            // 输出格式
            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            // 音频编码
            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            // 保存路径(示例路径,需适配 Android 10+ 作用域存储)
            String filePath = getExternalFilesDir(null) + "/call_recording_" + System.currentTimeMillis() + ".3gp";
            mediaRecorder.setOutputFile(filePath);
            
            mediaRecorder.prepare();
            mediaRecorder.start();
            Log.d(TAG, "开始录音: " + filePath);
        } catch (IOException | IllegalStateException e) {
            Log.e(TAG, "录音失败: " + e.getMessage());
        }
    }

    /**
     * 停止录音
     */
    private void stopRecording() {
        if (mediaRecorder != null) {
            try {
                mediaRecorder.stop();
                mediaRecorder.reset();
                mediaRecorder.release();
                mediaRecorder = null;
                Log.d(TAG, "录音已停止");
            } catch (RuntimeException e) {
                Log.e(TAG, "停止录音异常: " + e.getMessage());
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 注销监听器
        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
        stopRecording();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

3. 启动服务并检查权限(Activity 中调用)

复制代码
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

public class MainActivity extends AppCompatActivity {
    private static final int PERMISSION_REQUEST_CODE = 100;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 检查并请求权限
        if (checkPermissions()) {
            startCallRecordingService();
        }
    }

    private boolean checkPermissions() {
        String[] requiredPermissions = {
                Manifest.permission.RECORD_AUDIO,
                Manifest.permission.READ_PHONE_STATE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
        for (String permission : requiredPermissions) {
            if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, requiredPermissions, PERMISSION_REQUEST_CODE);
                return false;
            }
        }
        return true;
    }

    private void startCallRecordingService() {
        Intent serviceIntent = new Intent(this, CallRecordingService.class);
        // Android 8+ 需使用前台服务
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(serviceIntent);
        } else {
            startService(serviceIntent);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startCallRecordingService();
            }
        }
    }
}

关键问题与注意事项

  1. 音频源限制

    • VOICE_CALL 音频源需要系统级权限,普通应用无法使用。

    • 大部分设备使用 MIC 仅能录制本地麦克风声音(无法录制对方声音)。

  2. 厂商兼容性

    • 华为、小米等厂商可能屏蔽通话录音功能,需申请白名单或使用特殊 API。
  3. Android 版本适配

    • Android 9+ 禁止后台应用访问麦克风,需结合前台服务(Notification)实现。
  4. 法律与隐私

    • 通话录音需明确告知用户并取得同意(部分国家/地区要求双重确认)。

替代方案(推荐)

如果无法直接录制通话音频,可通过以下方式实现:

  1. 使用系统提供的通话录音接口 (如小米的 MiuiTelephony

  2. Root 设备后获取系统权限

  3. 接入第三方通话录音 SDK(如 Twilio、Agora)

建议根据实际需求选择合规方案。

相关推荐
何以解忧,唯有..6 分钟前
高并发下超卖问题解决方案:从数据库到分布式锁的完整实践
java
Brilliantwxx15 分钟前
【STM32】 I2C_EEPROM_test 工程(实战篇)
开发语言·stm32·单片机·嵌入式硬件·ecmascript
dadaobusi16 分钟前
学习:三层交换机
学习
峰向AI18 分钟前
Notion 太贵?这个 40K Star 的开源知识库,让你零成本搭建团队 wiki
github
行者全栈架构师19 分钟前
Spring Boot 接入 MaxKey 单点登录:6 个内部系统,一次登录全通行
java·vue.js·后端
清水白石00821 分钟前
Python 异步编程深度解析:Cancellation 到底是异常还是控制信号?从 asyncio 取消机制到企业级事务设计最佳实践
开发语言·python
kolyle27 分钟前
万级 QPS 下的 Token 分发系统架构:从 0 到 1 跑通 AI 时代的“水电煤“
开发语言·人工智能·系统架构·token·qps·极智词元·大模型私有化部署
Godikov28 分钟前
硬件异步事件下的业务一致性:智能柜领取/归还流程的竞态设计
android
Godikov28 分钟前
不用 Netty:Android 手写 TCP 客户端实战——自定义协议帧、粘包处理与可靠重连
android
木白CPP36 分钟前
Linux DMA驱动详解(二)-----DMA的使用者
java·linux·运维