当前位置: 首页
前端开发
Android手把手教WebRTC儿童远程监控App切换摄像头与桌面共享

Android手把手教WebRTC儿童远程监控App切换摄像头与桌面共享

热心网友 时间:2026-06-13
转载

概述 上一节,我们成功实现了嘟宝与嘟妈之间的WebRTC音视频通信,整体流程顺畅且逻辑清晰。嘟妈通过扫描二维码完成嘟宝的绑定,点击呼叫后,两端实时建立连接。嘟宝端摄像头与麦克风采集的多媒体视频流直接推送至嘟妈,画面与声音同步传输,体验流畅稳定。 嘟妈扫描二维码绑定嘟宝 嘟妈点击呼叫,与嘟宝建立Web

概述

上一节,我们成功实现了嘟宝与嘟妈之间的WebRTC音视频通信,整体流程顺畅且逻辑清晰。嘟妈通过扫描二维码完成嘟宝的绑定,点击呼叫后,两端实时建立连接。嘟宝端摄像头与麦克风采集的多媒体视频流直接推送至嘟妈,画面与声音同步传输,体验流畅稳定。

  • 嘟妈扫描二维码绑定嘟宝
  • 嘟妈点击呼叫,与嘟宝建立WebRTC实时通信
  • 嘟宝将摄像头、麦克风多媒体视频流发送至嘟妈

切换前后摄像头

接下来介绍一个非常实用的功能:远程切换摄像头。嘟妈端通过信令下发切换指令,嘟宝端摄像头可前置与后置之间无缝切换,视频流全程保持连接,画面跳转流畅,用户体验顺滑自然。

实现原理核心在于两点:获取相机采集工具,以及获取视频流。

   private VideoCapturer createCameraCapturer(boolean isFront) {
        Camera2Enumerator enumerator = new Camera2Enumerator(context.getApplicationContext());
        final String[] deviceNames = enumerator.getDeviceNames();
        for (String deviceName : deviceNames) {
            if (isFront ? enumerator.isFrontFacing(deviceName) : enumerator.isBackFacing(deviceName)) {
                VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
                mCamCapture = (CameraVideoCapturer) videoCapturer;
                if (videoCapturer != null) {
                    return videoCapturer;
                }
            }
        }
        return null;
    }

该函数逻辑十分明确:枚举设备上的所有摄像头,根据传入的 isFront 参数,返回前置或后置摄像头的采集实例。代码清晰直接,无冗余。

    private VideoTrack getVideoTrack(){
        surfaceTextureHelper = SurfaceTextureHelper.create("CaptureThread", eglBase.getEglBaseContext());
        VideoCapturer videoCapturer = createCameraCapturer(true);
        VideoSource videoSource = factory.createVideoSource(videoCapturer.isScreencast());
        videoCapturer.initialize(surfaceTextureHelper, context.getApplicationContext(), videoSource.getCapturerObserver());
        videoCapturer.startCapture(480, 640, 30);
        VideoTrack videoTrack=   factory.createVideoTrack("100", videoSource);
        videoTrack.enabled();
        return videoTrack;
    }

接着,getVideoTrack 方法调用上述函数,默认选用前置摄像头,启动采集后将视频流封装为 VideoTrack 并返回。注意在 createCameraCapturer 中有一行 mCamCapture = (CameraVideoCapturer) videoCapturer;,通过强制转换得到了 CameraVideoCapturer 引用,后续摄像头切换正依赖于此。

   public void changeCam(){
        if (mCamCapture != null) {
            mCamCapture.switchCamera(null);
        }    }

只需一行 switchCamera 调用,即可完成摄像头切换,稳定可靠。

屏幕共享

另一个实用场景是屏幕共享。嘟妈可通过信令远程查看嘟宝的屏幕,例如帮助孩子调试设备或演示操作流程,极为便捷。不过获取桌面屏幕需要用户授权——嘟宝启动时必须弹窗请求同意,否则无法采集屏幕数据。

实现步骤涉及三个环节:在后台服务中声明允许屏幕采集、在 MainActivity 中发起申请、用户同意后获取 Intent 变量以捕获桌面视频流。首先看清单文件中的配置:


其中 mediaProjection 类型的 foregroundServiceType 是必需的,它赋予服务在后台执行屏幕录制的能力。

 public void startprojectionManager(){
        @SuppressLint({"NewApi", "LocalSuppress"}) MediaProjectionManager projectionManager = (MediaProjectionManager)getSystemService(MEDIA_PROJECTION_SERVICE);
        @SuppressLint({"NewApi", "LocalSuppress"}) Intent intent = projectionManager.createScreenCaptureIntent();
        ActivityResultLauncher screenCaptureLauncher;
        screenCaptureLauncher=registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
            if (result.getResultCode() == RESULT_OK) {
                Intent data = result.getData();
                MyWebRtc.i=data;
            }
            else {
            }
        });
        screenCaptureLauncher.launch(intent);
    }

这段代码通过 MediaProjectionManager 创建屏幕捕获意图,并启动 ActivityResultLauncher 等待用户授权。若用户点击允许,result.getData() 返回的 Intent 将用于后续构建屏幕采集器,此处直接赋值给 MyWebRtc.i

public void getScreenVideo() {
        surfaceTextureHelperscreen = SurfaceTextureHelper.create("CaptureThread1", eglBase.getEglBaseContext());        VideoCapturer screenCapturer=new ScreenCapturerAndroid(i, new MediaProjection.Callback() {
            @Override
            public void onStop() {
                super.onStop();
            }
        }); // eglBaseContext 是你之前初始化的 EGL 上下文
        VideoSource screenVideoSource = factory.createVideoSource(screenCapturer.isScreencast());
        VideoTrack screenVideoTrack = factory.createVideoTrack("102", screenVideoSource);        // 2. 初始化并启动 ScreenCapturer
        // 注意:需要提前准备好 SurfaceTextureHelper
        screenCapturer.initialize(surfaceTextureHelperscreen, context.getApplicationContext(), screenVideoSource.getCapturerObserver());
        screenCapturer.startCapture(/* width */ 640, /* height */ 480, /* fps */ 25);        // 3. 执行替换的关键操作
//        localVideoSender.track().setEnabled(false);
        localVideoSender.setTrack(screenVideoTrack, /* takeOwnership= */ true);
    }

获得授权 Intent 后,使用 ScreenCapturerAndroid 实例化屏幕采集器,初始化并启动采集,最终得到屏幕的 VideoTrack。最后调用 localVideoSender.setTrack 将原摄像头视频流替换为屏幕视频流,即完成从摄像头画面到屏幕画面的平滑切换。

运行视频查看效果

来源:https://juejin.cn/post/7644742969188433926

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
如何用拖放在Flask看板应用中更新数据库状态

如何用拖放在Flask看板应用中更新数据库状态

在Flask看板应用中,通过HTML5拖放API结合前端fetch异步POST请求,将拖拽任务的task_id和target_state发送至后端路由;后端接收JSON后更新数据库并提交事务,实现跨列拖拽时实时更新状态。需注意将事件绑定到容器而非子元素,并在ondragover中阻止默认行为以确保drop触发。

时间:2026-07-09 07:01
如何用CSS :has()选择器快速实现悬停span显示相邻div

如何用CSS :has()选择器快速实现悬停span显示相邻div

利用CSS的:has()伪类选择器,通过` bar:has(> baz:hover)+ qux`实现悬停内联元素时显示相邻块级容器,解决了传统相邻兄弟选择器无法跨层级匹配的局限,可用于悬停图标显示详情框等交互场景。需注意浏览器兼容性和性能优化,避免过度使用影响渲染效率。

时间:2026-07-09 07:01
display:block居中段落文本的响应式实现方法

display:block居中段落文本的响应式实现方法

通过`display:block`与`max-width`限制宽度,配合`margin:auto`使段落块水平居中并实现响应式布局;同时用CSS统一控制段落间距,避免脱离文档流,提升可读性与维护性。

时间:2026-07-09 07:01
JavaScript代码去重:高效避免重复编写的技巧

JavaScript代码去重:高效避免重复编写的技巧

将重复代码中的变化点提取为参数,利用ES6模板字符串动态生成选择器,可消除重复、保持一致性。注意参数安全性,必要时进行白名单校验;批量化场景可扩展为数组形式;现代框架中更推荐数据驱动或组件化封装替代手动选择器。

时间:2026-07-09 07:00
使用容器查询单位cqw实现表单输入框相对于祖父容器百分比宽度

使用容器查询单位cqw实现表单输入框相对于祖父容器百分比宽度

利用CSS容器查询单位cqw,表单输入框宽度可直接基于祖父容器计算,绕过中间包装器尺寸干扰,实现简洁响应式布局,无需硬编码或JavaScript,显著降低维护成本,提升嵌套结构下的布局灵活性。

时间:2026-07-09 07:00
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜