REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX, AUDIO_DEVICE_IN_REMOTE_SUBMIX含义

【释义】

    在 Andorid 音频开发中,我们会看到叫做 REMOTE_SUBMIX 的音频类型,相应地在底层会有 AUDIO_DEVICE_OUT_REMOTE_SUBMIX 和 AUDIO_DEVICE_IN_REMOTE_SUBMIX 音频设备,在 audio_policy.conf 配置文件中也能看到 r_submix 设备。这次在开发中终于看到了这类音频的使用场景——使设备通过 WiFi 向 ChromeCast 设备传输 HDMI 数据(HDMI 同时含有视频数据和音频数据)。

    我们可以查看官方文档获得更详细的信息,如下:  

public static final int REMOTE_SUBMIX
Added in  API level 19

Audio source for a submix of audio streams to be presented remotely.

An application can use this audio source to capture a mix of audio streams that should be transmitted to a remote receiver such as a Wifi display. While recording is active, these audio streams are redirected to the remote submix instead of being played on the device speaker or headset.

Certain streams are excluded from the remote submix, including STREAM_RINGSTREAM_ALARM, and STREAM_NOTIFICATION. These streams will continue to be presented locally as usual.

Capturing the remote submix audio requires the CAPTURE_AUDIO_OUTPUT permission. This permission is reserved for use by system components and is not available to third-party applications.


    上面这段话的意思是 REMOTE_SUBMIX 表示被传输至远程接收设备(比如 WiFi 显示器,这次开发中使用的就是将 ChromeCast 设备接到一个显示器上)的音频,这类音频数据流会被重定向至远程输出而非在本地扬声器或耳机播放。但如果这其中包含了 STREAM_RING、STREAM_ALARM、STRAM_NOTIFICATION 这类音频数据,被包含的这些数据不会被发送到远程。

【参考资料】

    [1] 《MediaRecorder.AudioSource》




非常抱歉给出的之前的代码存在问题。在 Android 11录制系统声音是一个比较杂的任务,并且需要使用到较低级别的 API。以下是一个较完整的代码示例,演示如何在 Android 11 上录制系统声音: 首先,在你的 AndroidManifest.xml 文件中添加以下权限: ```xml <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> ``` 然后,创建一个 Service 类来处理录制系统声音的逻辑。在 Service 类中,我们将使用 MediaProjectionManager 和 MediaRecorder 来进行录制。 ```java public class RecordService extends Service { private MediaProjectionManager mediaProjectionManager; private MediaRecorder mediaRecorder; private VirtualDisplay virtualDisplay; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent.getAction().equals("start")) { startRecording(); } else if (intent.getAction().equals("stop")) { stopRecording(); } return START_STICKY; } private void startRecording() { mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); Intent permissionIntent = mediaProjectionManager.createScreenCaptureIntent(); permissionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(permissionIntent); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PERMISSION_CODE) { if (resultCode == RESULT_OK) { MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data); mediaRecorder = new MediaRecorder(); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.REMOTE_SUBMIX); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/recorded_audio.3gp"; mediaRecorder.setOutputFile(filePath); try { mediaRecorder.prepare(); } catch (IOException e) { e.printStackTrace(); } virtualDisplay = mediaProjection.createVirtualDisplay("RecordScreen", getWindowManager().getDefaultDisplay().getWidth(), getWindowManager().getDefaultDisplay().getHeight(), getResources().getDisplayMetrics().densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null); mediaRecorder.start(); } } } private void stopRecording() { if (virtualDisplay != null) { virtualDisplay.release(); } if (mediaRecorder != null) { mediaRecorder.stop(); mediaRecorder.reset(); } } } ``` 然后,在你的 Activity 中启动 Service: ```java Intent serviceIntent = new Intent(this, RecordService.class); serviceIntent.setAction("start"); startService(serviceIntent); ``` 以及停止录制: ```java Intent serviceIntent = new Intent(this, RecordService.class); serviceIntent.setAction("stop"); stopService(serviceIntent); ``` 请注意,由于安全性和隐私方面的考虑,Android 11 不再允许直接录制系统声音。因此,你需要在设备上启用 “开发者选项” 中的 “录制音频” 选项,或者使用模拟器来测试这段代码。 此外,为了在 Android 11 上启动前台服务,你还需要在你的应用中请求 `FOREGROUND_SERVICE` 权限,并在 Service 的 onStartCommand 方法中使用 `startForeground` 方法。关于前台服务的详细信息,请参考 Android 官方文档。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值