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

作者:技术拾光时间:2026-05-29 15:20:02浏览:277

概述 在上一节中,嘟宝与嘟妈之间的WebRTC音视频通信已完全跑通。整体流程并不复杂:嘟妈通过扫描二维码绑定嘟宝,点击呼叫后,两端建立实时连接。嘟宝端的摄像头和麦克风采集的多媒体流直接推送给嘟妈,画面与声音均可实现实时同步。 嘟妈扫描二维码绑定嘟宝 嘟妈点击呼叫,与嘟宝建立WebRTC通信 嘟宝将摄

概述

在上一节中,嘟宝与嘟妈之间的WebRTC音视频通信已完全跑通。整体流程并不复杂:嘟妈通过扫描二维码绑定嘟宝,点击呼叫后,两端建立实时连接。嘟宝端的摄像头和麦克风采集的多媒体流直接推送给嘟妈,画面与声音均可实现实时同步。

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

Android手把手编写儿童手机远程监控App: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 将原来的摄像头视频流替换为屏幕视频流,完成从摄像头画面到屏幕画面的切换。

运行视频查看效果