资讯动态

Flutter 相机插件 camera_android 完全指南:Camera2 实现原理、接入方式与模拟器录制限制

发布时间:2026/9/18 1:35:33 来源:尧图企业网站定制
Flutter 相机插件 camera_android 完全指南Camera2 实现原理、接入方式与模拟器录制限制【免费下载链接】packagesA collection of useful packages maintained by the Flutter team项目地址: https://gitcode.com/GitHub_Trending/pac/packages导读camera_android是 Flutter 官方camera插件在 Android 平台上的实现之一底层基于 Android 的 Camera2 库 构建负责把 Dart 层的相机 API 调用翻译为 Android 原生相机能力。本篇文章将带你了解它作为联邦插件Federated Plugin在 Flutter 相机体系中的定位、如何通过一条命令把它接入项目、它在 Dart 与 Java 两侧的实现架构以及官方明确警告的模拟器视频录制测试限制——读完你既能快速上手也能理解其底层工作原理避免在实际开发中踩坑。一、camera_android 在 Flutter 相机体系中的定位从仓库目录结构可以看出packages/camera下同时存在多个实现包camera/camera对外统一暴露 API 的“外壳”包app-facing 包camera/camera_android基于Camera2 库的 Android 实现camera/camera_android_camerax基于CameraX的另一种 Android 实现camera/camera_avfoundation、camera_web、camera_windows分别对应 iOS/macOS、Web、Windows 平台。这是 Flutter 官方推荐的endorsed federated plugin联邦插件模式camera_android通过implements: camera声明自己是camera平台接口的实现者。打开 pubspec.yaml 可以看到这段关键声明flutter: plugin: implements: camera platforms: android: package: io.flutter.plugins.camera pluginClass: CameraPlugin dartPluginClass: AndroidCamera其中implements: camera表示该插件“代言”camera包的 Android 平台实现package: io.flutter.plugins.camera与pluginClass: CameraPlugin指向 Android 原生入口类dartPluginClass: AndroidCamera指向 Dart 层实现类 AndroidCamera它在registerWith()中将自己注册为CameraPlatform.instance的默认实现。因此在 Flutter 工程中只要依赖了cameraAndroid 平台上会自动加载camera_android提供的实现开发者无需手动在 AndroidManifest 中注册任何东西。二、快速接入一条命令启用 Camera2 实现官方 README 给出的接入方式非常简洁。从camera: ^0.11.0开始如果你希望使用本插件而不是默认的camera_android_camerax作为 Android 端实现只需在项目根目录执行$ flutter pub add camera_androidflutter pub add会自动完成以下工作把camera_android写入项目的pubspec.yaml依赖中解析其依赖项camera_platform_interface、flutter_plugin_android_lifecycle、meta、stream_transform等见 pubspec.yaml由于它是camera的代言实现运行时CameraPlatform.instance会被替换为AndroidCamera实例。提示camera: ^0.11.0之后Flutter 官方在 Android 上的默认推荐实现是camera_android_cameraxCameraX若你的项目因特定原因需要使用基于 Camera2 的传统实现才显式添加camera_android。仓库 CHANGELOG 中也记录了这一变化过程。手动指定依赖的等价写法如果你更习惯手写pubspec.yaml等价做法是在dependencies中加入dependencies: camera: ^0.11.0 camera_android: ^0.10.11三、Dart 层实现剖析AndroidCamera 与 Pigeon 通道Dart 侧的实现集中在 lib/src/android_camera.dart。核心类AndroidCamera继承自CameraPlatform它的职责是把平台接口层的调用转译为对原生端的 Pigeon 调用并把原生端回调转译为 Dart 事件流。3.1 注册与初始化static void registerWith() { CameraPlatform.instance AndroidCamera(); }插件加载时通过这一行把AndroidCamera设为全局平台实例此后camera包内部所有调用都会路由到这里。3.2 调用原生端的方式Pigeon 生成代码AndroidCamera内部持有一个CameraApi实例由messages.g.dart通过 Pigeon 生成所有原生调用都走这个类型安全的通道FutureListCameraDescription availableCameras() async { final ListPlatformCameraDescription cameraDescriptions await _hostApi.getAvailableCameras(); // ...转换为 CameraDescription 列表 }从 CHANGELOG 可以看到camera_android在 0.10.915 / 0.10.914 / 0.10.913 一系列版本中把Dart→原生、原生→Dart以及getAvailableCameras都陆续迁移到了 Pigeon取代了早期的手写 MethodChannel。仓库中 pigeons 目录保存了接口定义源文件。3.3 相机事件流广播 StreamController原生端产生的事件初始化完成、分辨率变化、相机关闭、错误、视频录制完成、设备方向变化通过 Pigeon 回调进入 Dart 层再由AndroidCamera转发到不同的 Streamfinal StreamControllerCameraEvent cameraEventStreamController StreamControllerCameraEvent.broadcast(); StreamCameraEvent _cameraEvents(int cameraId) cameraEventStreamController.stream.where((event) event.cameraId cameraId); override StreamCameraInitializedEvent onCameraInitialized(int cameraId) { return _cameraEvents(cameraId).whereTypeCameraInitializedEvent(); }选择broadcast类型是因为可能存在多个CameraController同时订阅不同相机事件每个相机 ID 通过HostCameraMessageHandler建立独立的 Pigeon 消息通道后缀为$cameraId。3.4 图像流Image StreamingAndroidCamera明确支持图像流式输出supportsImageStreaming() true。onStreamedFrameAvailable通过plugins.flutter.io/camera_android/imageStream这个EventChannel接收原生端推送的帧数据并封装为CameraImageData提供给上层做实时分析等用途。相关实现可见_startStreamListener()与_onFrameStreamCancel()。3.5 预览 Widgetoverride Widget buildPreview(int cameraId) { return Texture(textureId: cameraId); }Android 端预览通过 Flutter 的Texture组件承载cameraId即原生端注册的纹理 ID这也是视频录制使用VideoSource.SURFACE作为输入源的原因——渲染与录制共享同一份 Surface 数据。四、Android 原生层实现CameraPlugin 与特性化架构原生端入口是 CameraPlugin.java它实现了FlutterPlugin与ActivityAware能够优雅处理 Activity 生命周期变化如旋转、配置变更并在合适时机创建CameraApiImpl完成消息通道的建立与权限请求的注册。4.1 特性化Feature架构从源码目录 features 可以看到原生实现把相机能力拆成了多个独立“特性”模块特性模块对应能力autofocus/focuspoint对焦模式与对焦点设置exposurelock/exposureoffset/exposurepoint曝光锁定、曝光补偿、曝光点flash闪光灯模式fpsrange帧率范围控制录制时生效jpegqualityJPEG 压缩质量对应 0.10.11 新增的setJpegImageQualitynoisereduction降噪开关resolution分辨率预设sensororientation传感器方向zoomlevel变焦控制它们统一继承自 CameraFeature.java由CameraFeatureFactory/CameraFeatures统一装配管理。这种设计让每个相机特性的启用、参数校验与状态查询职责单一也便于针对单个特性编写单元测试仓库android/src/test下每个 feature 都有对应测试类。4.2 权限处理相机权限由CameraPermissions.java负责权限结果通过addRequestPermissionsResultListener注册的回调接收。权限被拒绝时Dart 层会收到CameraException错误码与平台相关见下文示例章节的CameraAccessDenied、AudioAccessDenied等。五、视频录制与 MediaRecorderBuilderFPS/码率如何生效README 特别提到了MediaRecorder而原生端对MediaRecorder的封装正是 MediaRecorderBuilder.java。5.1 固定的配置顺序build()方法内有一段醒目的注释“Theres a fixed order that mediaRecorder expects.”。MediaRecorder对配置调用顺序非常敏感源码严格按照“音频源 → 视频源 → 输出格式 → 编码器 → 码率/帧率/尺寸 → 输出文件 → 方向提示 → prepare”的顺序执行任意打乱都可能导致IllegalStateException。5.2 编码档位选择双路径兼容if (SdkCapabilityChecker.supportsEncoderProfiles() encoderProfiles ! null) { // 新 APIEncoderProfilesAndroid 12 mediaRecorder.setOutputFormat(encoderProfiles.getRecommendedFileFormat()); ... } else if (camcorderProfile ! null) { // 兼容旧 APICamcorderProfile mediaRecorder.setOutputFormat(camcorderProfile.fileFormat); ... }从源码可以看出插件对 Android 12API 31及以上使用EncoderProfiles对旧版本回退到CamcorderProfile以此兼容不同系统版本上的编码配置获取方式。5.3 自定义 FPS 与比特率RecordingParameters携带了fps、videoBitrate、audioBitrate三个可选参数。当开发者显式传入大于 0 的值时优先使用自定义值否则回退到系统推荐的档位值int fps (parameters.fps ! null parameters.fps.intValue() 0) ? parameters.fps : videoProfile.getFrameRate();对应到 Dart 侧camera包的CameraController.withSettings以及本仓库示例中使用的MediaSettings可以把这些参数一路传递到原生端实现录制帧率与码率的精细控制见 CHANGELOG 0.10.9 条目Adds support to control video FPS and bitrate。5.4 一个需要留意的行为细节CHANGELOG 0.10.102 记录了一个值得注意的行为除非正在录制视频否则不会设置 FPS 范围。原因是在某些设备上固定 min/max FPS 会约束自动曝光算法导致预览画面偏暗副作用是仅传fps参数不会影响非录制状态下的预览帧率如果需要在图像流中做降帧处理官方建议在 Dart 侧按时间戳跳过帧。六、模拟器上测试视频录制的限制官方明确警告这是官方 README 用专门章节强调的问题属于使用本插件乃至整个 Android 相机生态时最容易踩的坑MediaRecorder在模拟器上无法正常工作Android 官方文档亦有说明。具体表现是当开启声音录制视频并尝试回放时视频时长不正确且只能看到第一帧。这意味着如果你在 Android 模拟器上编写、调试“带声音的视频录制 → 回放”这类测试用例很可能得到时长错误、画面卡在第一帧的结果这是平台层限制而不是你代码的 bug建议在真机上验证视频录制的完整链路采集、编码、落盘、回放模拟器更适合验证相机枚举、预览、拍照等不依赖MediaRecorder的功能若必须在 CI/模拟器上跑录制相关冒烟测试应把断言重点放在“录制流程不抛异常、文件成功生成”等层面而不是回放时长的精确性。七、示例工程完整的相机操作范式仓库自带示例应用 example/lib/main.dart它演示了从枚举相机到录制视频的完整流程是理解 API 用法的第一手资料。7.1 初始化 CameraControllerfinal cameraController CameraController( cameraDescription, mediaSettings: MediaSettings( resolutionPreset: kIsWeb ? ResolutionPreset.max : ResolutionPreset.medium, enableAudio: enableAudio, ), imageFormatGroup: ImageFormatGroup.jpeg, ); await cameraController.initialize();初始化完成后示例还会通过CameraPlatform.instance.getMaxZoomLevel(...)、getMinExposureOffset(...)等接口查询相机能力边界用于驱动 UI 中的变焦与曝光控件。7.2 统一的权限错误处理范式示例中对CameraException的code做了系统化分类处理} on CameraException catch (e) { switch (e.code) { case CameraAccessDenied: // 相机权限被拒绝 case CameraAccessDeniedWithoutPrompt: // iOS需到设置中开启 case CameraAccessRestricted: // 相机访问受限 case AudioAccessDenied: // 麦克风权限被拒绝 case AudioAccessDeniedWithoutPrompt: case AudioAccessRestricted: case cameraPermission: // Android 旧版错误码 ... } }注意CHANGELOG 0.10.0 记录了一个Breaking ChangeAndroid 的相机权限错误码被统一为与其他平台一致的格式。如果你的代码仍处理旧的cameraPermission异常码请更新为新的权限异常码体系。7.3 支持“录制中切换相机”AndroidCamera实现了setDescriptionWhileRecording示例中onNewCameraSelected在录制过程中切换相机时会走这条路径对应 CHANGELOG 0.10.5Allows camera to be switched while video recording。八、版本演进要点来自 CHANGELOG通过 CHANGELOG.md 可以梳理出该插件的重要演进脉络帮助你判断升级影响0.9.71从camera包中拆分为独立的联邦实现包成为现在的形态0.10.0统一 Android 权限错误码Breaking Change0.10.9支持视频 FPS 与比特率控制CameraController.withSettings0.10.913 ~ 15平台通信全面迁移到 Pigeon0.10.103初始化时等待 capture session 创建完成避免线程竞争0.10.102非录制状态不再设置 FPS 范围见上文 5.40.10.104修复主线程暂停时startImageStream的 OOM 问题0.10.11新增setJpegImageQuality控制 JPEG 压缩质量0.10.1016 / 17 / 18Gradle 构建文件迁移至 Kotlin DSL、修复拍照后闪光灯残留问题重置 AE/AF 触发器、最低 SDK 提升至 Flutter 3.38 / Dart 3.10。同时注意0.10.93 起移除了对 v1 Android embedding 的支持0.10.97 起移除了 API 21–23 的代码如果你的工程还停留在旧嵌入模式或极低系统版本升级前需要评估兼容性。总结camera_android作为 Fluttercamera生态中基于 Camera2 的 Android 实现架构上采用联邦插件模式Dart 层AndroidCamera Pigeon 通道 原生CameraPlugin原生端以特性化模块组织各类相机能力录制链路则由MediaRecorderBuilder按严格顺序装配。接入只需flutter pub add camera_android一条命令camera: ^0.11.0起。最后请务必牢记 README 的警告MediaRecorder在模拟器上无法可靠工作带声音录制回放会出现时长错误且只能看到第一帧视频录制相关功能请在真机上验证。【免费下载链接】packagesA collection of useful packages maintained by the Flutter team项目地址: https://gitcode.com/GitHub_Trending/pac/packages创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价