Android Q及以上系统音频捕获功能(声音内录)的简单实现

前言

现在越来越多的视频类APP,如抖音、快手、B站等等,都开放了音频捕获配置,也就是android:allowAudioPlaybackCapture="true"。因此学习如何捕获音频实现声音内录,是很有必要的。

第一步:设置allowAudioPlaybackCapture

很简单,在项目AndroidManifest.xml的application中增加一句android:allowAudioPlaybackCapture="true"

第二步:配置Service

        <service
            android:name=".RecordService"
            android:exported="true"
            android:foregroundServiceType="mediaProjection"
            android:enabled="true"/>

注意:本文只适用在Android Q及以上版本,因此必须使用前台服务方式startForegroundService()来启动服务。

请在Service的onCreate()中实现前台服务通知。

第三步:开始使用录制或投射内容

1.向用户询问是否开始使用录制或投射内容,注意:在Activity或Fragment中询问。

    if (currentResultCode != Activity.RESULT_OK || resultData == null) {
        MediaProjectionManager mediaProjectionManager
                = (MediaProjectionManager) this.getSystemService(MEDIA_PROJECTION_SERVICE);
        Intent screenCaptureIntent = mediaProjectionManager.createScreenCaptureIntent();
        startActivityForResult(screenCaptureIntent, REQUEST_SCREEN_CAPTURE_CODE);
        return;
    }

2.在onActivityResult()中获取currentResultCode和resultData

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_SCREEN_CAPTURE_CODE) {
            currentResultCode = resultCode;
            resultData = data;
        }
    }

3.将currentResultCode和resultData传递给Service

    Intent intent = new Intent(this, RecordService.class);
    intent.putExtra("resultData", resultData);
    intent.putExtra("resultCode", currentResultCode);
    startForegroundService(intent);

4.在Service的onStartCommand()中接收currentResultCode和resultData,获取MediaProjection实例(实例化要在前台Service中进行,这就是为什么要用Service的原因),并配置和启动AudioRecord

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int currentResultCode = intent.getIntExtra("resultCode", 0);
        Intent resultData = intent.getParcelableExtra("resultData");
        minBufferSize = AudioRecord.getMinBufferSize(16000,
                AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
        MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getBaseContext()
                .getSystemService(MEDIA_PROJECTION_SERVICE);
        MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(currentResultCode,
                Objects.requireNonNull(resultData));
        AudioRecord.Builder builder = new AudioRecord.Builder();
        builder.setAudioFormat(new AudioFormat.Builder()
                .setSampleRate(16000)
                .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
                .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
                .build())
                .setBufferSizeInBytes(minBufferSize);
        AudioPlaybackCaptureConfiguration config =
                new AudioPlaybackCaptureConfiguration.Builder(mediaProjection)
                        .addMatchingUsage(AudioAttributes.USAGE_MEDIA)
                        .addMatchingUsage(AudioAttributes.USAGE_UNKNOWN)
                        .addMatchingUsage(AudioAttributes.USAGE_GAME)
                        .build();
        builder.setAudioPlaybackCaptureConfig(config);
        try {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
                    == PackageManager.PERMISSION_GRANTED) {
                audioRecord = builder.build();
            }
        } catch (Exception e) {
            Log.e("录音器错误", "录音器初始化失败");
        }
        startRecord();
        return super.onStartCommand(intent, flags, startId);
    }

demo下载地址:https://download.csdn.net/download/sinat_39508948/86955519

完毕

猜你喜欢

转载自blog.csdn.net/sinat_39508948/article/details/127809541