You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用MediaRecorder录制LinearLayout区域内的屏幕操作内容

嘿,这个需求我帮不少开发者实现过!要只录制LinearLayout区域的屏幕内容,核心是利用MediaProjection的VirtualDisplay来精准指定捕获区域,而不是默认录制整个屏幕。下面给你一步步拆解实现:

实现特定LinearLayout区域的屏幕录制

首先明确:Android 5.0(API 21)及以上才支持系统级屏幕录制,所以你的目标设备得满足这个版本要求。

1. 先申请屏幕录制权限

录屏必须经过用户授权,先启动系统的权限申请界面:

private static final int REQUEST_CODE_SCREEN_RECORD = 100;
private MediaProjectionManager projectionManager;

// 触发权限申请
projectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
Intent recordIntent = projectionManager.createScreenCaptureIntent();
startActivityForResult(recordIntent, REQUEST_CODE_SCREEN_RECORD);

然后在onActivityResult里拿到授权后的MediaProjection实例:

private MediaProjection mMediaProjection;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_SCREEN_RECORD && resultCode == RESULT_OK) {
        mMediaProjection = projectionManager.getMediaProjection(resultCode, data);
        // 权限到手,开始初始化录制逻辑
        startTargetLayoutRecording();
    }
}

2. 获取LinearLayout的屏幕绝对区域

要精准捕获目标布局,得拿到它在屏幕上的真实坐标和尺寸。注意要等View布局完成后再获取(比如在onWindowFocusChanged或用ViewTreeObserver监听):

private Rect getTargetLayoutRect(LinearLayout targetLayout) {
    int[] location = new int[2];
    // 获取View在屏幕上的左上角坐标
    targetLayout.getLocationOnScreen(location);
    int left = location[0];
    int top = location[1];
    int right = left + targetLayout.getWidth();
    int bottom = top + targetLayout.getHeight();
    
    // 适配屏幕旋转:横屏时坐标和宽高需要交换调整
    Display display = getWindowManager().getDefaultDisplay();
    int rotation = display.getRotation();
    if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
        int temp = left;
        left = top;
        top = display.getWidth() - right;
        right = left + targetLayout.getHeight();
        bottom = top + targetLayout.getWidth();
    }
    
    return new Rect(left, top, right, bottom);
}

3. 配置MediaRecorder并创建指定区域的VirtualDisplay

这一步是核心:通过VirtualDisplay指定只捕获目标LinearLayout的区域,再把画面输出给MediaRecorder:

private MediaRecorder mMediaRecorder;
private VirtualDisplay mVirtualDisplay;

private void startTargetLayoutRecording() {
    LinearLayout targetLayout = findViewById(R.id.your_target_linear_layout);
    Rect targetRect = getTargetLayoutRect(targetLayout);
    
    // 初始化MediaRecorder
    mMediaRecorder = new MediaRecorder();
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 不需要录音可以删掉此行
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mMediaRecorder.setOutputFile(getOutputFilePath());
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    // 视频尺寸设置为目标布局的宽高
    mMediaRecorder.setVideoSize(targetRect.width(), targetRect.height());
    mMediaRecorder.setVideoFrameRate(30);
    mMediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024); // 调整码率控制清晰度
    
    try {
        mMediaRecorder.prepare();
    } catch (IOException e) {
        e.printStackTrace();
        return;
    }
    
    // 创建VirtualDisplay,指定捕获的屏幕区域
    mVirtualDisplay = mMediaProjection.createVirtualDisplay(
        "TargetRecordDisplay",
        targetRect.width(),
        targetRect.height(),
        getResources().getDisplayMetrics().densityDpi,
        DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
        mMediaRecorder.getSurface(),
        null, // 可选回调,用于监听虚拟显示状态
        null  // 可选Handler,指定回调线程
    );
    
    mMediaRecorder.start();
}

// 生成录制文件的保存路径(用应用私有目录,无需额外存储权限)
private String getOutputFilePath() {
    File recordDir = new File(getExternalFilesDir(null), "LayoutRecords");
    if (!recordDir.exists()) recordDir.mkdirs();
    return new File(recordDir, "record_" + System.currentTimeMillis() + ".mp4").getAbsolutePath();
}

4. 停止录制并释放资源

记得在合适的时机(比如Activity销毁、用户主动停止)释放资源,避免内存泄漏:

private void stopRecording() {
    if (mMediaRecorder != null) {
        try {
            mMediaRecorder.stop();
            mMediaRecorder.reset();
            mMediaRecorder.release();
        } catch (RuntimeException e) {
            // 处理录制未正常启动的异常情况
            e.printStackTrace();
        }
    }
    if (mVirtualDisplay != null) {
        mVirtualDisplay.release();
    }
    if (mMediaProjection != null) {
        mMediaProjection.stop();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    stopRecording();
}

额外注意事项

  • 动态布局适配:如果你的LinearLayout位置/大小会动态变化(比如滚动、布局更新),需要用ViewTreeObserver.OnGlobalLayoutListener监听布局变化,实时更新捕获区域并重新创建VirtualDisplay(重新创建会导致录制短暂中断,可根据需求做无缝切换处理)。
  • 权限补充:如果需要录音,别忘了申请RECORD_AUDIO权限;Android 10及以上用应用私有目录存储录制文件,无需申请WRITE_EXTERNAL_STORAGE。
  • 屏幕旋转适配:上面的代码做了基础的横竖屏适配,复杂场景可能需要结合Configuration监听屏幕方向变化,实时调整录制参数。

内容的提问来源于stack exchange,提问作者Ahsan Saeed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:06:41