声网支持在视频通话或互动直播场景中进行屏幕共享,你可以将主播或其他发言人的屏幕内容以视频的方式分享给其他用户观看,以提高沟通效率。
屏幕共享在音视频互动领域应用广泛,包括但不限于以下场景:
根据实际业务场景的不同,你可以选择以下任一方式调用 API 实现屏幕共享:
startScreenCapture
,然后调用 joinChannel
[2/2] 加入频道并设置 publishScreenCaptureVideo
为 true
,即可开始屏幕共享。startScreenCapture
,然后调用 updateChannelMediaOptions
更新频道媒体选项并设置 publishScreenCaptureVideo
为 true
,即可开始屏幕共享。startScreenCapture
时,SDK 会报告错误码 ERR_SCREEN_CAPTURE_PERMISSION_DENIED
(16) 和 ERR_SCREEN_CAPTURE_SYSTEM_NOT_SUPPORTED
(2)。 startScreenCapture
时,SDK 会报告错误码 ERR_SCREEN_CAPTURE_SYSTEM_AUDIO_NOT_SUPPORTED
(3)。setAudioScenario
方法设置音频场景为 AUDIO_SCENARIO_GAME_STREAMING
。本节介绍如何使用 Android SDK 实现屏幕共享。
声网 SDK 的屏幕共享通过插件实现,你需要集成 AgoraScreenShareExtension
动态库。
你可以根据你的集成方式,选择手动导入 aar 文件集成屏幕共享插件,或者通过 Maven Central 自动集成。
拷贝 SDK 中的 AgoraScreenShareExtension.aar
文件到 /app/libs/
目录下。
在 /app/build.gradle
文件的 dependencies
节点中添加如下行,以支持导入 aar 格式的文件。
implementation fileTree(dir: "libs", include: ["*.jar","*.aar"])
通过 Maven Central 集成 SDK 时,你可以修改 /Gradle Scripts/build.gradle(Module: <projectname>.app)
文件中 dependencies
的 implementation
字段添加依赖。
dependencies {
// 请使用具体的 SDK 版本号替换下面代码中的 x.y.z,可通过发版说明获取最新版本号
def agora_sdk_version = "x.y.z"
// 下述代码中包含 $,因此你必须使用 "",不能使用 ''
// 集成方案 1
implementation "io.agora.rtc:full-rtc-basic:${agora_sdk_version}"
implementation "io.agora.rtc:full-screen-sharing:${agora_sdk_version}"
implementation "io.agora.rtc:screen-capture:${agora_sdk_version}"
// 集成方案 2
implementation "io.agora.rtc:full-sdk:${agora_sdk_version}"
implementation "io.agora.rtc:full-screen-sharing:${agora_sdk_version}"
...
}
如果你的 Android 版本为 Android 9 及以上,需要在 /app/Manifests/AndroidManifest.xml
文件中添加如下前台服务权限,以避免应用退后台后被系统杀死。
android.permission.FOREGROUND_SERVICE
在需要将多路视频流同时发布到频道的场景下,你需要先加入一个频道,在该频道中发布一路视频流(比如屏幕共享流);然后加入第二个频道,在该频道中发布另一路视频流(比如摄像头采集的视频流),示例代码如下:
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (compoundButton.getId() == R.id.screenShare) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
if(b){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
getActivity().startForegroundService(fgServiceIntent);
}
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
ScreenCaptureParameters parameters = new ScreenCaptureParameters();
parameters.videoCaptureParameters.width = 720;
parameters.videoCaptureParameters.height = (int) (720 * 1.0f / metrics.widthPixels * metrics.heightPixels);
parameters.videoCaptureParameters.framerate = DEFAULT_SHARE_FRAME_RATE;
parameters.captureAudio = true;
// 开始屏幕共享
engine.startScreenCapture(parameters);
// 更新频道媒体选项,发布屏幕采集的音频和视频
options.publishScreenCaptureVideo = true;
options.publishScreenCaptureAudio = true;
// 不发布摄像头采集的视频
options.publishCameraTrack = false;
engine.updateChannelMediaOptions(options);
addScreenSharePreview();
}
else{
// 停止屏幕共享
engine.stopScreenCapture();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
getActivity().stopService(fgServiceIntent);
}
// 更新频道媒体选项,停止发布屏幕采集的视频和音频
options.publishScreenCaptureVideo = false;
options.publishScreenCaptureAudio = false;
engine.updateChannelMediaOptions(options);
}
screenSharePreview.setEnabled(b);
screenSharePreview.setChecked(b);
} else {
showAlert(getString(R.string.lowversiontip));
}
} else if (compoundButton.getId() == R.id.camera) {
if(b){
ChannelMediaOptions mediaOptions = new ChannelMediaOptions();
mediaOptions.autoSubscribeAudio = false;
mediaOptions.autoSubscribeVideo = false;
mediaOptions.publishScreenCaptureVideo = false;
// 在多频道中发布摄像头采集的视频
mediaOptions.publishCameraTrack = true;
mediaOptions.clientRoleType = Constants.CLIENT_ROLE_BROADCASTER;
mediaOptions.channelProfile = Constants.CHANNEL_PROFILE_LIVE_BROADCASTING;
rtcConnection2.channelId = et_channel.getText().toString();
rtcConnection2.localUid = new Random().nextInt(512)+512;
// 加入多频道
engine.joinChannelEx(null,rtcConnection2,mediaOptions,iRtcEngineEventHandler);
}
else{
engine.leaveChannelEx(rtcConnection2);
engine.startPreview(Constants.VideoSourceType.VIDEO_SOURCE_CAMERA_PRIMARY);
}
}else if (compoundButton.getId() == R.id.screenSharePreview) {
if(b){
addScreenSharePreview();
}else{
fl_screen.removeAllViews();
engine.stopPreview(Constants.VideoSourceType.VIDEO_SOURCE_SCREEN_PRIMARY);
}
}
}
我们在 GitHub 上提供开源示例项目供你参考。