在 Android 9 (Pie) 中,可以使用 MediaProjection API 来录制设备的内部声音。这种方式可以捕获设备的整体音频输出,包括应用程序、系统声音等。以下是一个详细的教程,介绍如何在 Android 9 上实现内部声音录制:
1. 权限申请
在录制内部声音之前,需要先申请两个权限:`RECORD_AUDIO`和`MEDIA_PROJECTION`。前者用于录制音频,后者用于屏幕录制。在 Android 9 中,还需要动态申请 `MEDIA_PROJECTION` 权限。
```java
private static final int REQUEST_CODE_PERMISSION = 123;
private static final int REQUEST_CODE_PROJECTION = 124;
// 申请权限
private void requestPermissions() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_CODE_PERMISSION);
} else {
startScreenCapture();
}
}
// 启动屏幕录制
private void startScreenCapture() {
Intent intent = new Intent(MediaProjection.ACTION_MEDIA_PROJECTION_START);
startActivityForResult(intent, REQUEST_CODE_PROJECTION);
}
```
2. 获取 MediaProjection 实例
在用户授予权限后,系统会返回 `RESULT_OK` 和一个 `Intent`。我们需要从 `Intent` 中获取 `MediaProjection` 实例,以便进行后续的录制操作。
```java
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_PROJECTION && resultCode == RESULT_OK) {
mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
startRecording();
}
}
```
3. 设置 MediaProjection 参数并开始录制
有了 `MediaProjection` 实例后,我们可以开始录制内部声音了。需要设置录制参数,如视频编码器、音频编码器、分辨率、帧率等。下面是一个示例:
```java
private void startRecording() {
// 设置视频编码器
MediaCodecInfo videoCodecInfo = selectVideoEncoder("video/avc"); // H.264
MediaFormat videoFormat = MediaFormat.createVideoFormat("video/avc", WIDTH, HEIGHT);
videoFormat.setInteger(MediaFormat.KEY_BIT_RATE, VIDEO_BITRATE);
videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
videoFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
videoFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, videoCodecInfo.getCapabilitiesForType("video/avc").colorFormats[0]);
// 设置音频编码器
MediaCodecInfo audioCodecInfo = selectAudioEncoder("audio/mp4a-latm"); // AAC
MediaFormat audioFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", SAMPLE_RATE, CHANNEL_COUNT);
audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, AUDIO_BITRATE);
// 创建 MediaProjectionCallback 并开始录制
mMediaProjectionCallback = new MediaProjectionCallback();
mMediaProjection.registerCallback(mMediaProjectionCallback, null);
startMediaRecorder(videoFormat, audioFormat);
}
```
4. 实现 MediaRecorder 录制
在上一步中,我们设置了视频和音频的编码参数,接下来就可以创建 `MediaRecorder` 并开始录制了。
```java
private void startMediaRecorder(MediaFormat videoFormat, MediaFormat audioFormat) {
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.AVC);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mMediaRecorder.setVideoSize(WIDTH, HEIGHT);
mMediaRecorder.setVideoFrameRate(FRAME_RATE);
mMediaRecorder.setVideoEncodingBitRate(VIDEO_BITRATE);
mMediaRecorder.setAudioEncodingBitRate(AUDIO_BITRATE);
mMediaRecorder.setAudioSamplingRate(SAMPLE_RATE);
mMediaRecorder.setAudioChannels(CHANNEL_COUNT);
mMediaRecorder.setOutputFile(OUTPUT_FILE_PATH);
mMediaRecorder.prepare();
mMediaRecorder.start();
}
```
5. 停止录制并释放资源
录制完成后,需要停止 `MediaRecorder` 并释放资源。同时也需要注销 `MediaProjection` 的回调。
```java
private void stopRecording() {
mMediaRecorder.stop();
mMediaRecorder.release();
mMediaRecorder = null;
mMediaProjection.unregisterCallback(mMediaProjectionCallback);
mMediaProjection.stop();
mMediaProjection = null;
}
```
以上就是在 Android 9 上实现内部声音录制的完整流程。需要注意的是,这种方式需要动态申请 `MEDIA_PROJECTION` 权限,并且在用户授权后获取 `MediaProjection` 实例进行录制。同时,还需要设置合适的编码参数,以确保录制的视频和音频质量。
总结一下,在 Android 9 上实现内部声音录制的主要步骤包括:
1. 申请 `RECORD_AUDIO` 和 `MEDIA_PROJECTION` 权限
2. 启动屏幕录制并获取 `MediaProjection` 实例
3. 设置视频和音频编码参数,创建 `MediaRecorder` 并开始录制
4. 在录制完成后停止 `MediaRecorder` 并释放资源
通过这种方式,我们就可以在 Android 9 上实现对设备内部声音的录制,满足各种应用场景的需求。