如何使用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
相关产品推荐
相关产品推荐

