はじめに
今回はFlutterでカメラを使用して、プレビューの表示と写真の撮影を行いたいと思います。カメラとかデバイス周りは面倒そうと思っていましたが、かなり簡単に実装できたので紹介します。
準備
まずはパッケージのcameraをpubspec.yamlに追加しましょう。
1 | flutter pub add camera |
pubspec.yamlに追加されていれば成功です。
1 | camera: ^0.9.8+1 |
次は、iOSでカメラを使用するために、Info.plistに以下の内容を追加します。
1 2 3 4 | <key>NSCameraUsageDescription</key> <string>カメラ使います</string> <key>NSMicrophoneUsageDescription</key> <string>マイクを使います</string> |
また、cameraパッケージの動作環境は、iOSでは10以上、Androidは21以上になっています。それ以下のバージョンでは動作しません。
実装
プレビューの表示
最初に、カメラのプレビューをアプリで表示したいと思います。
まずは、デバイスで使用できるカメラの一覧を取得します。
1 2 3 4 5 6 7 8 9 10 11 12 | 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()); } |
CameraDescriptionの中身は以下のようになっており、バックカメラやフロントカメラを取得することができます。
1 | CameraDescription(com.apple.avfoundation.avcapturedevice.built-in_video:0, CameraLensDirection.back, 90) |
次にカメラを制御するためのCameraControllerを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | class CameraApp extends StatefulWidget { /// Default Constructor const CameraApp({Key? key}) : super(key: key); @override State<CameraApp> createState() => _CameraAppState(); } class _CameraAppState extends State<CameraApp> { 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': print('User denied camera access.'); break; default: print('Handle other errors.'); break; } } }); } |
CameraControllerの第一引数に最初に取得したCameraDescriptionを、第二引数に解像度の指定を入れます。ResolutionPreset.maxを指定することで使用できる最大の解像度を設定してくれます。CameraControllerを生成したらinitializeを行い、CameraControllerの準備は完了です。
1 2 3 4 5 6 7 8 9 | @override Widget build(BuildContext context) { if (!controller.value.isInitialized) { return Container(); } return MaterialApp( home: CameraPreview(controller), ); } |
最後にCameraPreviewにCameraControllerをセットすれば、カメラのプレビュー表示は完了です。
写真を撮る
プレビューの表示が出来たので、次は写真を取りたいと思います。写真撮影は、CameraControllerのtakePictureを呼び出すことで、簡単に行うことができます。プレビューの表示箇所にFloatingActionButtonを設置してtakePictureを呼びたいと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @override Widget build(BuildContext context) { return MaterialApp( home:Scaffold( body: Center( child: controller.value.isInitialized ? CameraPreview(controller) : Container() ), floatingActionButton: FloatingActionButton( onPressed: () async { // 写真を撮る final imageFile = await controller.takePicture(); // path を出力 print(imageFile.path); }, child: const Icon(Icons.camera_alt), ), ) ); } |
パスを出力すると以下のようになっているので、jpgで画像が保存されているのがわかります。
1 | flutter: /var/mobile/Containers/Data/Application/xxx/Documents/camera/pictures/CAP_xxx.jpg |
さいごに
swiftでカメラを使用するときなど、結構面倒なコードを書かなくてはいけないので気後れしていましたが、かなり簡単にプレビュー表示など行えるので気軽に実装できますね。