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

Flutter中屏幕共享的实现原理、所需条件及实施步骤

Flutter 屏幕共享实现指南:获取内容与Widget展示

前置条件

  • 稳定版Flutter环境(推荐3.0+)
  • Android端:
    • 目标SDK版本≥21(MediaProjection API最低要求)
    • 需申请RECORD_AUDIO、WRITE_EXTERNAL_STORAGE权限(Android 13+需动态申请)
  • iOS端:
    • 需创建Broadcast Extension Target(Xcode操作)
    • 配置NSMicrophoneUsageDescription、NSScreenCaptureUsageDescription权限描述
    • 仅支持真机测试,模拟器不支持录屏功能

核心实现步骤

1. 系统权限申请

  • Android:调用MediaProjectionManager发起权限请求,用户授权后获取MediaProjection实例
  • iOS:通过ReplayKit触发系统录屏授权弹窗,同时确保Broadcast Extension已正确配置

2. 获取屏幕画面流

  • Android:利用MediaProjection创建虚拟显示器,将屏幕画面转为SurfaceTexture,再传递给Flutter端
  • iOS:通过Broadcast Extension的RPBroadcastSampleHandler捕获视频帧,将帧数据编码后传递给主App

3. 在Flutter Widget中展示

将原生传递的画面流转为Flutter的Texture Widget(最直接的方式),或通过视频播放器组件解码播放

4. 生命周期管理

  • 页面销毁时停止屏幕捕获,释放MediaProjection/ReplayKit资源
  • 监听权限状态变化,用户取消授权时立即终止共享

代码示例

Flutter端核心代码(基于flutter_media_projection插件)

先在pubspec.yaml添加依赖:

dependencies:
  flutter_media_projection: ^0.1.5 # 替换为最新版本

页面实现:

import 'package:flutter/material.dart';
import 'package:flutter_media_projection/flutter_media_projection.dart';

class ScreenShareDemo extends StatefulWidget {
  const ScreenShareDemo({super.key});

  @override
  State<ScreenShareDemo> createState() => _ScreenShareDemoState();
}

class _ScreenShareDemoState extends State<ScreenShareDemo> {
  final FlutterMediaProjection _mediaProjection = FlutterMediaProjection();
  int? _textureId;

  Future<void> _startCapture() async {
    final permission = await _mediaProjection.requestPermission();
    if (permission == PermissionResult.granted) {
      final textureId = await _mediaProjection.startScreenCapture(
        width: MediaQuery.of(context).size.width.toInt(),
        height: MediaQuery.of(context).size.height.toInt(),
        fps: 30,
      );
      setState(() => _textureId = textureId);
    }
  }

  void _stopCapture() {
    if (_textureId != null) {
      _mediaProjection.stopScreenCapture();
      setState(() => _textureId = null);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('屏幕共享测试')),
      body: Column(
        children: [
          Expanded(
            child: _textureId != null 
                ? Texture(textureId: _textureId!) 
                : const Center(child: Text('点击下方按钮开始共享')),
          ),
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: ElevatedButton(
              onPressed: _textureId == null ? _startCapture : _stopCapture,
              child: Text(_textureId == null ? '开始共享' : '停止共享'),
            ),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _stopCapture();
    super.dispose();
  }
}

Android配置(AndroidManifest.xml)

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />

<!-- 若targetSdk≥33,需添加动态权限申请逻辑 -->

iOS配置

  1. 在Xcode中为项目添加Broadcast Extension Target(File → New → Target → Broadcast Extension)
  2. 修改主App的Info.plist:
<key>NSMicrophoneUsageDescription</key>
<string>屏幕共享需要麦克风权限捕捉音频</string>
<key>NSScreenCaptureUsageDescription</key>
<string>屏幕共享需要录屏权限捕捉画面</string>
  1. 修改Broadcast Extension的Info.plist,确保RPBroadcastProcessMode设为RPSystemBroadcastProcessMode

注意事项

  • 性能优化:根据需求调整分辨率、帧率,避免高配置导致的卡顿
  • 权限异常处理:用户拒绝权限时需给出明确提示,引导用户去设置页开启
  • iOS端:Broadcast Extension的代码需自行实现帧数据传递逻辑(部分插件已封装此步骤)
  • Android 12+:需处理后台屏幕捕获的限制,避免应用退到后台后共享中断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 12:05:21