Flutter Camera 插件(camera 包)完整接入指南:相机预览、拍照录像、图像流与权限生命周期管理
Flutter Camera 插件camera 包完整接入指南相机预览、拍照录像、图像流与权限生命周期管理【免费下载链接】packagesA collection of useful packages maintained by the Flutter team项目地址: https://gitcode.com/GitHub_Trending/pac/packages本篇技术指南以 Flutter 团队官方维护的camera插件位于本仓库packages/camera/camera为对象系统讲解如何在 Android、iOS、Web 三端快速接入摄像头能力从平台工程配置Info.plist 权限声明、CameraX/Camera2 后端选型、核心 API 调用链availableCameras→CameraController.initialize→CameraPreview到拍照、录像、Dart 侧图像流、生命周期释放与六类权限错误码的完整处理方案。读完本文你将能够基于本仓库源码搭建一个可运行的全屏相机应用并理解其底层平台分发机制与各控制接口的实现细节。一、插件概览与平台支持camera是 Flutter 官方插件federated plugin即联邦插件架构用于访问设备摄像头支持 iOS、Android 与 Web 三大平台。其定位与核心能力见 README 与 pubspec.yaml 中的描述控制相机、预览相机画面、采集图像与视频并将图像缓冲区流式传输到 Dart 层。平台支持矩阵平台支持范围AndroidSDK 24iOSiOS 13.0Web见camera_web包camera_web 实现从 pubspec.yaml 可以看出该插件采用联邦分发策略各平台由独立实现包承接flutter: plugin: platforms: android: default_package: camera_android_camerax ios: default_package: camera_avfoundation web: default_package: camera_web dependencies: camera_android_camerax: ^0.7.4 camera_avfoundation: ^0.10.2 camera_platform_interface: ^2.13.1 camera_web: ^0.3.3 flutter_plugin_android_lifecycle: ^2.0.2即Android 默认走 camera_android_camerax基于 CameraXiOS 走 camera_avfoundation基于 AVFoundationWeb 走 camera_web。作为 Flutter 团队维护的官方插件其版本约束为 SDK^3.12.0、Flutter3.44.0以当前仓库pubspec.yaml为准。核心功能特性根据 README 的 Features 一节插件提供四项核心能力实时相机预览在 Widget 中展示实时相机画面拍照捕获快照并保存为文件录像录制视频图像流从 Dart 侧访问相机图像流逐帧回调。二、环境准备与依赖安装在你的 Flutter 项目pubspec.yaml中添加依赖dependencies: camera: ^0.12.1camera是 endorsed官方背书联邦插件只需依赖这一个包各平台实现包会在构建时自动解析引入。添加依赖后执行flutter pub get即可。三、平台工程配置iOSInfo.plist 权限声明在ios/Runner/Info.plist中添加两行配置Privacy - Camera Usage Description键NSCameraUsageDescription相机使用用途说明Privacy - Microphone Usage Description键NSMicrophoneUsageDescription麦克风使用用途说明录像需要音频。以文本方式编辑Info.plist时加入如下 XML 片段来自 READMEkeyNSCameraUsageDescription/key stringyour usage description here/string keyNSMicrophoneUsageDescription/key stringyour usage description here/string说明iOS 在应用访问相机/麦克风前必须声明用途字符串否则系统会直接终止应用。即使你的功能不需要录音也建议一并声明麦克风用途因为录像 API 默认enableAudio true。AndroidCameraX 与 Camera2 后端选型Android 端默认使用 camera_android_camerax基于 CameraX实现它对更多设备有更好的兼容性但存在一些局限性例如对部分设备的支持限制详见该包 README 的 limitations 列表。如果希望使用基于 Camera2 的 camera_android 实现该实现不包含 CameraX 的那些限制需按照该包 README 的 Usage 说明进行配置替换。此外若希望在应用退到后台时仍允许图像流image streaming还需要额外的配置步骤具体见 camera_android_camerax 的后台图像流说明。补充当前仓库中同时维护了camera_android_cameraxCameraX与camera_androidCamera2两套 Android 实现二者目录并列于packages/camera/下可根据设备兼容性需求选择。Web 集成Web 平台的实现细节请参考 camera_web 包 的 README其中包含 Web 平台特有的限制说明如部分 API 不可用、图像格式差异等。四、核心 API 与标准使用流程camera包的公开 API 统一从 lib/camera.dart 导出它重新导出了平台接口层的核心类型CameraDescription、CameraException、CameraLensDirection、CameraLensType、ExposureMode、FlashMode、FocusMode、ImageFormatGroup、ResolutionPreset、VideoStabilizationMode、XFile以及CameraController、CameraImage、CameraPreview三个核心类。标准的使用链路分为四步1. 枚举可用摄像头availableCameras()final ListCameraDescription cameras await availableCameras();该函数在源码中实现为对平台接口的一层薄封装camera_controller.dartFutureListCameraDescription availableCameras() async { return CameraPlatform.instance.availableCameras(); }它返回设备上所有可用摄像头的描述列表每个CameraDescription包含摄像头标识、lensDirection前摄front、后摄back、外接external见 camera_description.dart等信息。初始化失败时可能抛出CameraException。2. 创建控制器CameraControllerfinal CameraController controller CameraController( cameras[0], // 选定的摄像头描述 ResolutionPreset.max, // 分辨率预设 );CameraController继承自ValueNotifierCameraValuecamera_controller.dart因此可以通过监听其valueCameraValue类型来响应状态变化。构造函数支持以下参数参数默认值说明description必填摄像头描述对象resolutionPreset必填分辨率预设影响录像与拍照质量enableAudiotrue录制的视频是否包含音频fpsnull帧率帧/秒若提供则覆盖分辨率预设的设置videoBitratenull视频编码比特率若提供则覆盖分辨率预设audioBitratenull音频编码比特率若提供则覆盖分辨率预设imageFormatGroupnull原始图像格式为null时回退到平台默认格式ResolutionPreset是一个目标分辨率不保证精确——设备不支持时平台实现会回退到更高或更低分辨率。其定义见 resolution_preset.dartenum ResolutionPreset { low, // iOS 上 352x288Android/Web 约 240p medium, // 约 480p high, // 约 720p veryHigh, // 约 1080p ultraHigh, // 约 2160p max, // 设备支持的最高分辨率 }3. 初始化controller.initialize()await controller.initialize();初始化成功后controller.value.isInitialized变为truevalue.previewSize携带预览尺寸。从源码camera_controller.dart可见其内部依次完成订阅设备方向变化事件onDeviceOrientationChanged通过CameraPlatform.instance.createCameraWithSettings创建相机会话等待onCameraInitialized事件调用initializeCamera并更新CameraValue设置isInitialized、previewSize、exposureMode、focusMode等状态。4. 展示预览CameraPreviewWidget build(BuildContext context) { if (!controller.value.isInitialized) { return Container(); } return CameraPreview(controller); }CameraPreview是展示实时相机画面的 Widgetcamera_preview.dart。从源码可以看到它内部通过ValueListenableBuilder监听控制器状态根据方向自动计算AspectRatio并且在 Android 上使用RotatedBox按设备方向旋转预览画面_wrapInRotatedBox、_getQuarterTurns方法确保竖屏/横屏下预览方向正确。五、拍照takePicture()控制器初始化完成后即可调用拍照final XFile file await controller.takePicture();返回的XFile指向保存图片的文件可配合Image.file移动端或Image.networkWeb见示例代码中的注释说明展示若上一次拍照尚未返回就再次调用会抛出CameraExceptioncode 为Previous capture has not returned yet.见 camera_controller.dart拍照期间value.isTakingPicture为true可调用setJpegImageQuality(int quality)设置 JPEG 压缩质量1~100仅对 JPEG 格式生效不支持时平台会忽略而不是抛错。六、录像startVideoRecording / stopVideoRecording// 开始录制 await controller.startVideoRecording(); // 结束录制返回视频文件 final XFile videoFile await controller.stopVideoRecording();关键细节camera_controller.dartstartVideoRecording({onAvailable, enablePersistentRecording true})可传入onAvailable回调将视频帧同时流式传给该回调enablePersistentRecording默认true表示持久录制——只能通过显式调用stopVideoRecording停止且会忽略生命周期事件、录制期间的setDescription等通常会导致录制停止的事件目前仅在 Android 上生效pauseVideoRecording()/resumeVideoRecording()暂停/恢复录制仅 iOS 与 Android SDK 24 可用录制状态可通过value.isRecordingVideo、value.isRecordingPaused判断iOS 上可提前调用prepareForVideoRecording()预准备录制会话以消除开始录像时的预览卡顿该操作在 Android 与 Web 上是 no-op。七、Dart 侧图像流startImageStream若需要对每一帧图像做实时处理如扫码、目标检测可使用图像流await controller.startImageStream((CameraImage image) { // 处理每一帧图像 });源码要点camera_controller.dart回调类型为onLatestImageAvailable始终返回最新一帧中间帧会被丢弃需要先通过supportsImageStreaming()确认平台支持与CameraPreview同时运行时建议使用ResolutionPreset.lowhigh及以上在低端设备上会造成预览明显掉帧图像流进行中不可同时录像会抛异常停止用stopImageStream()回调中的CameraImagecamera_image.dart包含format图像格式、width/height、planes像素平面列表含字节数据与行距bytesPerRow等布局信息以及lensAperture、sensorExposureTime、sensorSensitivity等元数据注意它不是可直接用于 UI 展示的资源。八、生命周期状态处理重要从0.5.0 版本起插件不再自动处理生命周期变化开发者必须自行控制相机资源的创建与释放否则可能导致异常行为。推荐通过混入WidgetsBindingObserver并重写didChangeAppLifecycleState来处理示例取自 example/lib/main.dart与 README 一致override void didChangeAppLifecycleState(AppLifecycleState state) { final CameraController? cameraController controller; // App state changed before we got the chance to initialize. if (cameraController null || !cameraController.value.isInitialized) { return; } if (state AppLifecycleState.inactive) { cameraController.dispose(); } else if (state AppLifecycleState.resumed) { _initializeCameraController(cameraController.description); } }处理要点进入inactive如来电、下拉通知栏、切后台时dispose()释放相机资源回到resumed时基于保存的description重新初始化控制器每次重建前务必检查isInitialized避免对未初始化控制器误操作dispose()是幂等的源码中_isDisposed标志保证重复调用安全返回且会取消设备方向订阅并释放平台侧相机资源camera_controller.dart。九、相机访问权限与错误处理初始化相机控制器时可能抛出权限错误开发者应当妥善处理。CameraExceptioncamera_exception.dart由code与description构成以下是可能出现的全部权限错误码README错误码触发场景CameraAccessDenied用户拒绝相机访问权限CameraAccessDeniedWithoutPrompt目前仅 iOS用户此前已拒绝过权限iOS 不允许二次弹出授权弹窗用户需前往设置 隐私 相机手动开启CameraAccessRestricted目前仅 iOS相机访问受限制用户无法授权如家长控制AudioAccessDenied用户拒绝音频访问权限AudioAccessDeniedWithoutPrompt目前仅 iOS用户此前已拒绝过音频权限需前往设置 隐私 麦克风手动开启AudioAccessRestricted目前仅 iOS音频访问受限制用户无法授权如家长控制在官方示例 example/lib/main.dart 中针对上述每种错误码都给出了对应的 UI 反馈策略} on CameraException catch (e) { switch (e.code) { case CameraAccessDenied: showInSnackBar(You have denied camera access.); case CameraAccessDeniedWithoutPrompt: // iOS only showInSnackBar(Please go to Settings app to enable camera access.); case CameraAccessRestricted: // iOS only showInSnackBar(Camera access is restricted.); case AudioAccessDenied: showInSnackBar(You have denied audio access.); case AudioAccessDeniedWithoutPrompt: // iOS only showInSnackBar(Please go to Settings app to enable audio access.); case AudioAccessRestricted: // iOS only showInSnackBar(Audio access is restricted.); default: _showCameraException(e); } }十、进阶控制能力CameraController还提供了丰富的拍摄控制接口全部定义于 camera_controller.dart可在实际应用中按需组合能力API说明闪光灯setFlashMode(FlashMode)off/auto/always/torch见 flash_mode.dart缩放getMinZoomLevel()/getMaxZoomLevel()/setZoomLevel(double)缩放值应在最小与最大之间超出会抛CameraException对焦setFocusMode(FocusMode)/setFocusPoint(Offset?)对焦点坐标为归一化值0,0~1,1null恢复默认曝光setExposureMode(ExposureMode)/setExposurePoint(Offset?)/getMinExposureOffset()/getMaxExposureOffset()/setExposureOffset(double)曝光偏移单位为 EV1 EV 表示亮度翻倍自动取整到最近步进防抖getSupportedVideoStabilizationModes()/setVideoStabilizationMode(mode, {allowFallback true})allowFallback为false且不支持指定模式时抛ArgumentError方向锁定lockCaptureOrientation([DeviceOrientation?])/unlockCaptureOrientation()不传参数时锁定当前设备方向预览暂停pausePreview()/resumePreview()支持手动暂停/恢复预览切换摄像头setDescription(CameraDescription)录像中调用时需配合持久录制Android官方示例 example/lib/main.dart 展示了这些能力的完整集成双指手势缩放_handleScaleUpdate中通过setZoomLevel实现、点击取景器同时对焦与测光onViewFinderTap中同时调用setExposurePoint与setFocusPoint、闪光灯/曝光/对焦模式切换面板、前后摄像头切换、拍摄缩略图展示等是学习生产级相机交互的绝佳参考。十一、完整可运行示例以下是 README 提供的最小全屏相机预览示例与 example/lib/readme_full_example.dart 完全一致import package:camera/camera.dart; import package:flutter/material.dart; late ListCameraDescription _cameras; Futurevoid main() async { WidgetsFlutterBinding.ensureInitialized(); _cameras await availableCameras(); runApp(const CameraApp()); } /// CameraApp is the Main Application. class CameraApp extends StatefulWidget { /// Default Constructor const CameraApp({super.key}); override StateCameraApp createState() _CameraAppState(); } class _CameraAppState extends StateCameraApp { late CameraController controller; override void initState() { super.initState(); controller CameraController(_cameras[0], ResolutionPreset.max); controller .initialize() .then((_) { if (!mounted) { return; } setState(() {}); }) .catchError((Object e) { if (e is CameraException) { switch (e.code) { case CameraAccessDenied: // Handle access errors here. break; default: // Handle other errors here. break; } } }); } override void dispose() { controller.dispose(); super.dispose(); } override Widget build(BuildContext context) { if (!controller.value.isInitialized) { return Container(); } return MaterialApp(home: CameraPreview(controller)); } }要点回顾WidgetsFlutterBinding.ensureInitialized()确保在runApp前完成平台通道初始化因为availableCameras()是异步的平台调用初始化完成后通过setState触发重建渲染CameraPreviewinitialize()失败时通过CameraException.code区分错误类型在dispose()中释放控制器。十二、测试与验证camera包在仓库中配有完整的 Dart 单元测试见 camera 包 test 目录覆盖控制器初始化、拍照、录像、图像流、生命周期释放、错误处理等核心路径平台层还有对应的原生单元测试如 camera_android_camerax 测试、camera_avfoundation 测试。你可以参考这些测试理解各 API 的预期行为与异常路径并在自己的项目中编写类似测试来验证相机功能的正确性。总结本文基于仓库中的 camera 包 及其 README完整覆盖了 Flutter 相机能力接入的全流程平台工程配置iOS 权限声明、Android CameraX/Camera2 选型、核心 API 调用链枚举摄像头 → 创建并初始化控制器 → 预览/拍照/录像/图像流、生命周期资源管理、六类权限错误码处理以及闪光灯、缩放、对焦、曝光等进阶控制。配合源码级说明读者既能获得开箱即用的实战代码也能理解每个接口背后的平台分发机制与状态模型从而在自己的 Flutter 应用中稳健地集成相机能力。【免费下载链接】packagesA collection of useful packages maintained by the Flutter team项目地址: https://gitcode.com/GitHub_Trending/pac/packages创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

深入理解 Dagger TypeScript SDK 的 ErrorID:错误对象唯一标识符的类型定义与实战解析

深入理解 Dagger TypeScript SDK 的 ErrorID:错误对象唯一标识符的类型定义与实战解析

深入理解 Dagger TypeScript SDK 的 ErrorID:错误对象唯一标识符的类型定义与实战解析 【免费下载链接】dagger Automation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud 项目地址: https://gitcode.com/GitHub_…

2026/9/21 8:17:59 阅读更多 →
拿 Claude Chat 拉取素材,TaoToken 只提供 Key 和 Base URL

拿 Claude Chat 拉取素材,TaoToken 只提供 Key 和 Base URL

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 4:28:04 阅读更多 →
FPGA实现UDP协议栈:verilog-ethernet开源工程学习与上板调试

FPGA实现UDP协议栈:verilog-ethernet开源工程学习与上板调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 22:43:53 阅读更多 →

最新新闻

石察卡图解原理:3个核心考点拆解版本升级痛点

石察卡图解原理:3个核心考点拆解版本升级痛点

石察卡图解原理:3个核心考点拆解版本升级痛点 版本升级后 API 全变了,石察卡图解原理能救命。 别再对着报错日志发呆,大厂面试最爱问这个。 用图解原理看透石察卡,面试直接拿高分。 考点梳理:为什么石察卡成为高频面试题…

2026/9/22 2:27:22 阅读更多 →
应的繁体字避坑指南:3步搞定环境配置完整示例

应的繁体字避坑指南:3步搞定环境配置完整示例

应的繁体字避坑指南:3步搞定环境配置完整示例 配置环境就卡半天,这种痛谁懂?很多开发者在搭建项目时,因为一个不起眼的字符编码问题,导致依赖安装失败、构建报错,甚至前端页面出现乱码。今天要解决的核心痛点,就是“应的繁体字”这一类特殊字符在不同…

2026/9/22 2:27:21 阅读更多 →
成都入户性能优化源码解析:3步解决报错堆积

成都入户性能优化源码解析:3步解决报错堆积

成都入户性能优化源码解析:3步解决报错堆积 盯着屏幕上一长串红色的 StackTrace,心里那个慌啊。每一行调用栈都像天书,尤其是当业务逻辑嵌套了七八层,报错信息指向某个陌生的类名时,根本不知道从哪下手。很多刚接触后端开发的兄弟,面对这种…

2026/9/22 2:27:21 阅读更多 →
剑三抓马插件性能优化实战:3个底层原理让你面试不再卡壳

剑三抓马插件性能优化实战:3个底层原理让你面试不再卡壳

剑三抓马插件性能优化实战:3个底层原理让你面试不再卡壳 面试被问原理答不上来,是无数转岗开发者的噩梦。当你还在纠结业务逻辑时,面试官却盯着底层实现追问细节,这种落差感让人窒息。今天不讲虚的,直接拆解【剑三抓马插件】在【性能优化】上的底层逻辑…

2026/9/22 2:27:21 阅读更多 →
文字扫描识别软件面试避坑:3个核心考点助你搞定性能优化

文字扫描识别软件面试避坑:3个核心考点助你搞定性能优化

文字扫描识别软件面试避坑:3个核心考点助你搞定性能优化 很多开发者学了 OCR 基础语法,却卡在“怎么把识别准确率提到 99% 以上”这一步。别慌,这正是面试大厂时最容易被问到的 性能优化…

2026/9/22 2:26:20 阅读更多 →
车架号查询车辆信息实战:5种后端方案对比与最佳实践

车架号查询车辆信息实战:5种后端方案对比与最佳实践

车架号查询车辆信息实战:5种后端方案对比与最佳实践 学会语法却不知怎么搭项目?这是很多开发者从教程走向生产环境时最大的拦路虎。尤其是面对像 车架号查询车辆信息 这种典型的高频业务场景,很多人只会写 SELECT * FROM cars…

2026/9/22 2:26:20 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/21 3:13:20 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/21 2:19:36 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →