[Flutter] Camera 패키지

uengmin·2025년 1월 15일

Flutter

목록 보기
16/20
post-thumbnail

기존 MAUI 프로젝트에서 카메라를 사용할 때 Camera.MAUI 패키지를 사용해서 개발을 진행했다.

[Flutter] QR_Code_Scanner 사용법

MAUI에서는 카메라를 통해 사진을 찍거나 QR Scan을 할 때 Camera.MAUI 패키지 하나로 가능했는데 기존에 포스팅 했던 QR_Code_Scanner 사용법을 참고해보면 플루터에서는 따로 따로 사용해야 한다.

공식 문서
https://pub.dev/packages/camera

그러면 카메라로 이미지를 촬영해보자.

1. 설치

  • pubspce.yaml에 camera를 추가
  camera: ^0.10.3+2
  • pub get 하기

포스팅 기준 camera 패키지의 가장 최신 버전은 camera 0.11.0+2인데 테스트를 해보니 카메라 화면이 이상하게 가로로 나오는 오류가 있어 버전 다운그레이드하여 설치 추천

2. 권한 추가

  • Android => android > app > src > main > AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA"/>
  • android > app > build.gradle
android {
    // ...
defaultConfig {
        minSdkVersion 21
    }
}
  • iOS => ios > Runner > info.plist
<!-- Permission options for the `camera` group -->
	<key>NSCameraUsageDescription</key>
	<string>라벨 QR코드 조회를 위해 카메라 사용 권한을 허용하시겠습니까?</string>
	<key>NSMicrophoneUsageDescription</key>
	<string>마이크 권한을 허용하시겠습니까?</string>

3. 코드 작성

  • 호출
Future<void> main() async {
  // 비동기 데이터 다룸으로 아래 코드 추가
  // 다음에 호출되는 함수 모두 실행 끝날 때까지 기다림
  WidgetsFlutterBinding.ensureInitialized();

  // 기기에서 사용 가능한 카메라 목록 불러오기
  final cameras = await availableCameras();

  // 사용 가능한 카메라 중 첫 번째 카메라 사용
  final firstCamera = cameras.first;

  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      home: LoginPage(
        camera: firstCamera,
      ),
    ),
  );
  • 카메라 화면
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';

class LockclosePage extends StatefulWidget {
  const LockclosePage({super.key, required this.camera});

  final CameraDescription camera;

  
  State<LockclosePage> createState() => _LockclosePageState();
}

class _LockclosePageState extends State<LockclosePage> {
  late CameraController _controller;
  late Future<void> _initializeControllerFuture;

  
  void initState() {
    super.initState();
    // 카메라 관리하는 컨트롤러 생성
    _controller = CameraController(
      widget.camera,
      ResolutionPreset.high,
    );
    _initializeControllerFuture = _controller.initialize();
  }

  
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: const Text('봉인 증명'),
      ),
      body: Column(
        children: [
          FutureBuilder<void>(
            future: _initializeControllerFuture,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                // 미리보기
                return CameraPreview(_controller);
              } else {
                return Center(child: CircularProgressIndicator());
              }
            },
          ),
        ],
      ),
      // 버튼 누를 시 카메라 화면의 캡쳐본을 보여주는 화면으로 이동
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.camera_alt),
        onPressed: () async {
          try {
            await _initializeControllerFuture;
            // 현재 카메라 화면 캡쳐
            final image = await _controller.takePicture();

            if (!mounted) return;

            // 사진 보여주기
            await Navigator.of(context).push(
              MaterialPageRoute(
                builder: (context) => DisplayPictureScreen(
                  imagePath: image.path,
                ),
              ),
            );
          } catch (e) {
            print(e);
          }
        },
      ),
    );
  }
}

// --------------------------------
// 찍은 사진 보여주는 위젯
class DisplayPictureScreen extends StatelessWidget {
  final String imagePath;

  const DisplayPictureScreen({super.key, required this.imagePath});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('캡쳐 화면')),
      body: Image.file(File(imagePath)),
    );
  }
}

결과

0개의 댓글