在 Android 开发中,实现通话录音功能通常涉及到对系统通话的拦截和录音。由于通话录音涉及到用户隐私和安全性,Android 系统对此有严格的限制和要求。在 Android 10(API 级别 29)及以上版本中,直接访问通话录音功能变得更为复杂,因为 Google 引入了运行时权限和更严格的隐私政策。
方案一:使用系统内置功能
如果你的应用目标是 Android 10 以下版本,你可以使用 TelephonyManager
的 addProximityListener
方法来监听通话状态,并结合 AudioRecord
类来录制音频。例如:
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.content.Context;public class CallRecorder {private AudioRecord audioRecord;private boolean isRecording = false;private Thread recordingThread;private static final int SAMPLE_RATE = 44100;private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO;private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;private void startRecording() {int minBufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT);audioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_CALL, SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT, minBufferSize * 10);audioRecord.startRecording();isRecording = true;recordingThread = new Thread(() -> {byte[] buffer = new byte[minBufferSize];while (isRecording) {audioRecord.read(buffer, 0, buffer.length);// 处理录音数据,例如写入文件等}});recordingThread.start();}private void stopRecording() {if (isRecording) {isRecording = false;audioRecord.stop();audioRecord.release();recordingThread.interrupt();}}
}
方案二:使用 Android 10+ 的权限和 API 变更
在 Android 10 及更高版本中,你需要动态请求 RECORD_AUDIO
和 FOREGROUND_SERVICE
权限,并且使用前台服务来进行录音,以符合 Google 的隐私政策。你可以使用 MediaProjection
API 来捕获音频流。例如:
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.content.Intent;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.io.*;
import android.media.*;
import androidx.annotation.*;public class MainActivity extends AppCompatActivity {private MediaProjectionManager mProjectionManager;private MediaProjection mMediaProjection;private AudioFormat mAudioFormat;private AudioTrack mAudioTrack;private ExecutorService mExecutor = Executors.newSingleThreadExecutor();private static final int REQUEST_CODE = 1000; // 请求代码,自定义即可private ActivityResultLauncher<Intent> requestPermissionLauncher; // 处理权限请求的Launcher对象。private static final String[] REQUIRED_PERMISSIONS = new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.FOREGROUND_SERVICE}; // 需要的权限数组。private boolean hasPermissions = false; // 标记是否拥有所有权限。默认为false。表示不拥有权限。private boolean isScreenCapturing = false; // 表示是否正在进行屏幕捕获。默认为false。表示不进行屏幕捕获。默认为false。表示不进行屏幕捕获。默认为false。表示不进行屏幕捕获。默认为false。表示不进行屏幕捕获。默认为false。表示不进行屏幕捕获。默认为false。表示不进行屏幕捕获。默认为