Flutter相机功能插件camera2的使用

Flutter相机功能插件camera2的使用

插件简介

camera 是一个用于访问设备摄像头的 Flutter 插件,支持 iOS、Android 和 Web 平台。通过该插件,您可以实现相机预览、拍照和录像等功能。

pub package
功能 Android 支持情况 iOS 支持情况 Web 支持情况
支持版本 SDK 21+ iOS 11.0+ 详见 camera_web 文档

特性

  • 在小部件中显示实时相机预览。
  • 可以捕获快照并保存到文件。
  • 支持视频录制。
  • 可以通过 Dart 访问图像流。

安装

首先,在 pubspec.yaml 文件中添加 camera 作为依赖项:

dependencies:
  camera: ^latest_version

然后运行以下命令以更新依赖项:

flutter pub get

iOS 配置

ios/Runner/Info.plist 中添加以下两行配置:

<key>NSCameraUsageDescription</key>
<string>您的相机使用描述</string>
<key>NSMicrophoneUsageDescription</key>
<string>您的麦克风使用描述</string>

Android 配置

android/app/build.gradle 文件中将最小 SDK 版本设置为 21 或更高:

minSdkVersion 21

注意:MediaRecorder 类在模拟器上可能无法正常工作。具体问题可参考官方文档:MediaRecorder


Web 集成

对于 Web 平台的具体集成说明,请参考 camera_web 包的文档。


处理生命周期状态

从版本 0.5.0 开始,camera 插件不再自动处理生命周期变化。开发者需要手动控制相机资源。如果未正确处理,可能会导致意外行为(例如 issue #39109)。可以通过重写 didChangeAppLifecycleState 方法来实现:

[@override](/user/override)
void didChangeAppLifecycleState(AppLifecycleState state) {
  final CameraController? cameraController = controller;

  if (cameraController == null || !cameraController.value.isInitialized) {
    return;
  }

  if (state == AppLifecycleState.inactive) {
    cameraController.dispose();
  } else if (state == AppLifecycleState.resumed) {
    _initializeCameraController(cameraController.description);
  }
}

处理相机访问权限

初始化相机控制器时可能会抛出权限错误,应妥善处理这些错误。以下是可能的错误类型及描述:

  • CameraAccessDenied: 用户拒绝了相机访问权限。
  • CameraAccessDeniedWithoutPrompt: iOS 用户之前已拒绝权限,无法再次提示。
  • CameraAccessRestricted: iOS 设备上的相机访问被限制。
  • AudioAccessDenied: 用户拒绝了音频访问权限。
  • AudioAccessDeniedWithoutPrompt: iOS 用户之前已拒绝权限,无法再次提示。
  • AudioAccessRestricted: iOS 设备上的音频访问被限制。

示例代码

以下是一个简单的示例,展示如何在 Flutter 应用中实现全屏相机预览。

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

late List<CameraDescription> _cameras;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  _cameras = await availableCameras();
  runApp(const CameraApp());
}

/// CameraApp 是主应用类。
class CameraApp extends StatefulWidget {
  /// 默认构造函数
  const CameraApp({super.key});

  [@override](/user/override)
  State<CameraApp> createState() => _CameraAppState();
}

class _CameraAppState extends State<CameraApp> {
  late CameraController controller;

  [@override](/user/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':
            // 处理权限错误
            break;
          default:
            // 处理其他错误
            break;
        }
      }
    });
  }

  [@override](/user/override)
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    if (!controller.value.isInitialized) {
      return Container();
    }
    return MaterialApp(
      home: CameraPreview(controller),
    );
  }
}

更复杂的功能示例

以下是一个更复杂的示例,展示了如何实现相机的多种功能,如闪光灯模式切换、变焦控制等。

import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

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

  [@override](/user/override)
  State<CameraExampleHome> createState() => _CameraExampleHomeState();
}

// 其他代码省略...

更多关于Flutter相机功能插件camera2的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter相机功能插件camera2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,camera 插件是用于访问设备相机功能的主要插件。虽然 camera2 是 Android 原生的相机 API,但在 Flutter 中,我们通常使用 camera 插件来访问相机功能,它内部可能会使用 camera2 API(在 Android 上)。

以下是如何在 Flutter 中使用 camera 插件的基本步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 camera 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  camera: ^0.10.0+1

然后运行 flutter pub get 来安装依赖。

2. 配置 Android 和 iOS 项目

Android

android/app/src/main/AndroidManifest.xml 文件中添加相机权限:

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

iOS

ios/Runner/Info.plist 文件中添加相机权限:

<key>NSCameraUsageDescription</key>
<string>We need access to your camera to take photos.</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need access to your microphone to record videos.</string>

3. 初始化相机

在 Flutter 中初始化相机并显示预览:

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

class CameraApp extends StatefulWidget {
  @override
  _CameraAppState createState() => _CameraAppState();
}

class _CameraAppState extends State<CameraApp> {
  CameraController? _controller;
  List<CameraDescription>? cameras;

  @override
  void initState() {
    super.initState();
    _initializeCamera();
  }

  Future<void> _initializeCamera() async {
    cameras = await availableCameras();
    _controller = CameraController(
      cameras![0], // 使用第一个摄像头
      ResolutionPreset.medium,
    );

    await _controller!.initialize();
    if (!mounted) return;
    setState(() {});
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (_controller == null || !_controller!.value.isInitialized) {
      return Container();
    }
    return Scaffold(
      appBar: AppBar(title: Text('Camera Example')),
      body: CameraPreview(_controller!),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          final image = await _controller!.takePicture();
          print('Image saved to ${image.path}');
        },
        child: Icon(Icons.camera),
      ),
    );
  }
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MaterialApp(
    home: CameraApp(),
  ));
}

4. 运行应用

现在你可以运行应用,并看到相机预览。点击浮动按钮可以拍照,照片的路径会打印到控制台。

5. 处理相机权限

在 Android 和 iOS 上,相机权限是必需的。你可以使用 permission_handler 插件来请求和管理权限。

dependencies:
  permission_handler: ^10.0.0

然后在代码中请求权限:

import 'package:permission_handler/permission_handler.dart';

Future<void> _checkPermissions() async {
  var status = await Permission.camera.status;
  if (!status.isGranted) {
    await Permission.camera.request();
  }
}

initState 中调用 _checkPermissions 以确保应用有权限访问相机。

6. 处理不同摄像头

你可以通过 cameras 列表来切换不同的摄像头(例如前置和后置摄像头):

void _switchCamera() async {
  if (cameras == null || cameras!.length < 2) return;

  final newCamera = _controller!.description == cameras![0] ? cameras![1] : cameras![0];
  _controller = CameraController(
    newCamera,
    ResolutionPreset.medium,
  );

  await _controller!.initialize();
  if (!mounted) return;
  setState(() {});
}

7. 录制视频

你还可以使用 camera 插件来录制视频:

Future<void> _startRecording() async {
  if (!_controller!.value.isInitialized) {
    return;
  }
  await _controller!.startVideoRecording();
}

Future<void> _stopRecording() async {
  if (!_controller!.value.isRecordingVideo) {
    return;
  }
  final video = await _controller!.stopVideoRecording();
  print('Video saved to ${video.path}');
}
回到顶部