NERoom 房间组件
Android
动态与公告
更新日志
产品简介
产品介绍
功能特性
产品优势
使用限制
快速开始
接入流程
开通 NERoom 房间组件
下载 SDK和 Demo
集成 SDK
初始化SDK
搭建直播间
账号集成与登录
房间管理
创建房间
进入房间
监听房间事件
离开房间
删除房间
房间属性
成员管理
查询房间成员信息
移除成员
成员属性
修改成员角色
即时消息
进入和离开聊天室
消息发送
消息接收
音视频通话
加入和退出音视频房间
设置音频属性
本地视频预览
静音和取消静音
开启和关闭视频
屏幕共享
虚拟背景
云信美颜
第三方美颜
伴音和音效
耳返
麦位管理
互动白板
直播
场景实践
PK 直播组件
会议组件
语聊房组件
最佳实践
超大房间直播互动
复用 IM 的账号
错误码
常见问题

屏幕共享

更新时间: 2022/10/31 15:24:28

在大型会议或在线教育等场景中,为了满足提升沟通效率的需求,主讲人或老师需要将本端的屏幕内容分享给远端参会者或在线学生观看。NERoom 支持屏幕共享功能,帮助您实时分享本端设备的屏幕内容,满足在线教育、互动娱乐、金融面签、视频会议等低延时高互动场景的需求。

功能介绍

通过 NERoom SDK 可以在视频通话中实现屏幕共享,主播或连麦者可以将自己的屏幕内容,以视频的方式分享给远端参会者或在线观众观看,从而提升沟通效率,一般适用于多人视频聊天、在线会议以及在线教育场景。

  • 视频会议场景中,参会者可以在会议中将本地的文件、数据、网页、PPT 等画面分享给其他与会者,让其他与会者更加直观的了解讨论的内容和主题。

  • 在线课堂场景中,老师可以通过屏幕共享将课件、笔记、教学内容等画面展示给远端的其他学生观看,降低传统教学模式下的沟通成本,提升教育场景的用户体验。

NERoom SDK 以辅流的形式实现屏幕共享,即单独为屏幕共享开启一路上行的视频流,摄像头的视频流作为主流,屏幕共享的视频流作为辅流,两路视频流并行,主播同时上行摄像头画面和屏幕画面两路画面。

注意事项

  • 在开始屏幕共享前,请确保已在您的项目中实现基本的实时音视频功能。
  • 您需要先调用 joinRoom 进入房间,再通过 joinRtcChannel 加入音视频房间,才能使用屏幕共享功能。
  • MediaProjection 等 API 需要 Android API level 21+,使用方法请参考 Google MediaProjection API 文档。
  • Android 10 及以后的版本屏幕共享系统要求开启一个前台服务,因此需要在 AndroidManifest.xml 中添加 service,同时将 compileSdkVersion 设置为 29。请根据您的业务需求添加 service。

本端共享屏幕

配置步骤

  1. AndroidManifest.xml 文件中添加前台服务 ScreenShareService
  2. 通过 MediaProjection 创建 ScreenCaptureIntent 请求屏幕共享权限,并将 intent 传递给 startActivityForResult()
  3. 在加入房间之后调用 startScreenShare 方法开启屏幕共享,以辅流形式发送屏幕共享内容。调用此方法时,您需要传入请求权限后返回的 screenShareResultData,并设置 MediaProjection.Callback() 以接收屏幕共享状态回调。
  4. 开启屏幕共享后,房间内其他成员会收到 onMemberScreenShareStateChanged 回调,通知房间内其他成员关于您屏幕共享状态的变更。
  5. 若您要结束屏幕共享,请调用 stopScreenShare 方法关闭辅流形式的屏幕共享。

示例代码

//需要在 AndroidManifest.xml 中添加前台服务
       <service
            android:name=".services.ScreenShareService"
            android:foregroundServiceType="mediaProjection">
            <intent-filter>
                <action android:name="com.netease.Yunxin.ScreenShare" />
            </intent-filter>
        </service>
        
public class RoomActivity extends AppCompatActivity {
    private ScreenShareServiceConnection mServiceConnection;
    private ScreenShareService mScreenService;
      private class ScreenShareServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            if (service instanceof ScreenShareService.ScreenShareBinder) {
                mScreenService = ((ScreenShareService.ScreenShareBinder) service).getService();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mScreenService = null;
        }
    }

    private ActivityResultLauncher<Intent> launcher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {

                @Override
                public void onActivityResult(ActivityResult result) {
                    Log.d(TAG, "onActivityResult,result:" + result.getResultCode());
                    if (result.getResultCode() == Activity.RESULT_OK) {
                        mScreenService.startScreenShare(currentRoomContext.getRtcController(), result.getData(),
                                new MediaProjection.Callback() {

                                    @Override
                                    public void onStop() {
                                        super.onStop();
                                        Log.d(TAG,"屏幕共享结束");
                                    }
                                }, new NECallback<Unit>() {

                                    @Override
                                    public void onResult(int code, @Nullable String message, @Nullable Unit unit) {
                                        Log.d(TAG, "code:" + code);
                                        if (code == NEErrorCode.SUCCESS) {
                                            Log.d(TAG,"开始屏幕共享");
                                        }
                                    }
                                });
                    }
                }
            });
            
      @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_room);
        bindScreenService();
           findViewById(R.id.startScreenShare).setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(
                        Context.MEDIA_PROJECTION_SERVICE);
                launcher.launch(mediaProjectionManager.createScreenCaptureIntent());
            }
        });
        findViewById(R.id.stopScreenShare).setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                mScreenService.stopScreenShare(currentRoomContext.getRtcController(), new NECallback<Unit>() {

                    @Override
                    public void onResult(int code, @Nullable String message, @Nullable Unit unit) {
                        Log.d(TAG,"结束屏幕共享");
                    }
                });
            }
        });
    }
    
        @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindScreenService();
    }
    
     private void bindScreenService() {
        Intent intent = new Intent();
        intent.setClass(this, ScreenShareService.class);
        mServiceConnection = new ScreenShareServiceConnection();
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }
    
       private void unbindScreenService() {
        if (mServiceConnection != null) {
            unbindService(mServiceConnection);
        }
    }
}

观看远端屏幕共享

注意事项

必须在指定用户开启了屏幕共享辅流通道后,即收到 onMemberScreenShareStateChanged 回调后,才能订阅该远端用户的辅流。

    /**
     * 成员屏幕共享状态回调
     * @param member 成员
     * @param isSharing 是否正在进行屏幕共享
     */
    fun onMemberScreenShareStateChanged(member: NERoomMember, isSharing: Boolean)

配置步骤

  1. 远端用户加入音视频房间。
  2. 收到 onMemberScreenShareStateChanged 其他用户开启屏幕共享辅流通道的回调。
  3. 调用 subscribeRemoteVideoSubStream 方法订阅远端的屏幕共享辅流视频,订阅之后才能接收远端的辅流视频数据。调用此方法时,您需要设置指定用户的 Uuid,同时设置 subscribe 参数为 true。
  4. 收到 onMemberScreenShareStateChanged 其他用户关闭屏幕共享辅流通道的回调,结束屏幕共享。

示例代码

if (remoteMember.isSharingScreen()) {
         NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
         NERoomContext currentRoomContext = roomService.getRoomContext(roomUuid);
         if (currentRoomContext != null) {
         currentRoomContext.getRtcController().subscribeRemoteVideoSubStream(remoteMember.getUuid(), true,
                                                new NECallback2<Unit>() {

                                                    @Override
                                                    public void onSuccess(
                                                            @Nullable Unit unit) {
                                                        Log.d(TAG, "success");
                                                    }

                                                    @Override
                                                    public void onError(int code,
                                                                        @Nullable String message) {
                                                        Log.d(TAG, "error");
                                                    }
                                                });
                                    }
         }

关闭某成员的屏幕共享

在会议等场景中,主持人可以关闭某成员的屏幕共享。

您可以在云信控制台上配置某角色是否具备该权限,只有具备该权限的角色才可以执行此操作。

配置步骤

  1. 调用 stopMemberScreenShare关闭房间内某成员的屏幕共享。相关的参数说明如下表所示。
参数 说明
userUuid 待关闭屏幕共享的成员的 uuid。
callback 回调
  1. 房间内其他成员会收到 onMemberScreenShareStateChanged 回调,通知房间内其他成员关于屏幕共享状态的变更。

示例代码

        NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
        NERoomContext roomContext = roomService.getRoomContext(roomUuid);
        if (roomContext != null) {
            String userUuid = "uuid";
            roomContext.getRtcController().stopMemberScreenShare(userUuid, new NECallback2<Unit>() {
                @Override
                public void onSuccess(@Nullable Unit unit) {
                    Log.d(TAG,"success");
                }

                @Override
                public void onError(int code, @Nullable String message) {
                    Log.d(TAG,"error");
                }
            });
        }

API 参考

方法 功能描述
joinRoom 加入 NERoom 的房间。
joinRtcChannel 加入音视频房间。
startScreenShare 开始屏幕共享。
stopScreenShare 结束屏幕共享。
onMemberScreenShareStateChanged 成员屏幕共享状态回调。
subscribeRemoteSubStreamVideo 订阅或取消订阅指定远端用户辅流视频。
stopMemberScreenShare 关闭房间内某成员的屏幕共享。
此文档是否对你有帮助?
有帮助
我要吐槽
  • 功能介绍
  • 注意事项
  • 本端共享屏幕
  • 配置步骤
  • 示例代码
  • 观看远端屏幕共享
  • 注意事项
  • 配置步骤
  • 示例代码
  • 关闭某成员的屏幕共享
  • 配置步骤
  • 示例代码
  • API 参考