Flutter勉強記録2日目～カメラを使って景色を見るだけのアプリを作ってみる～

# 前回のあらすじ
Flutterのインストールをして、サンプルコードを動かした。
[「Flutter勉強記録1日目～インストールからサンプルコードを走らせるまで～」](https://qiita.com/ikeguma_Na/items/274223827b49f304b228)

今日使っているプロジェクトは、昨日生成した初期のサンプルコードを使いまわしています。

# この記事ですること

- カメラを使ってファインダー越しの景色を見るアプリを作る
- カメラアプリ**ではない**。（写真撮影機能が無い）
- [pub.dev](https://pub.dev/)なる場所にあった[カメラのプラグイン](https://pub.dev/packages/camera)を使う

# 環境
- Windows10
- VScode
- camera: ^0.8.1+7
- Flutter 2.2.3 • channel stable • https://github.com/flutter/flutter.git  
- Framework • revision f4abaa0735 (6 weeks ago) • 2021-07-01 12:46:11 -0700
- Engine • revision 241c87ad80
- Tools • Dart 2.13.4

# 1. カメラを使うために設定を変更する

[cameraプラグインのReadme > Installation](https://pub.dev/packages/camera#installation)に沿って、設定を変更していく。

cameraプラグインを使うには、iOSはバージョン10.0以上、Androidはsdk version 21以上（Android5.0  LOLLIPOP）以上が必要らしいので、その設定をする。

## iOS
**注意**
ドキュメントに従って設定をしていますが、iOSの実機を持っていないため動作確認はできていません。

1.　`ios/Runner/Info.plist`を開く
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528682/0877e092-10dd-e13a-a372-e92278e99ef7.jpeg)

2.　最初の方に以下の文をコピーして、上の方に貼り付ける。

```xml
<key>NSCameraUsageDescription</key>
<string>Can I use the camera please?</string>
<key>NSMicrophoneUsageDescription</key>
<string>Can I use the mic please?</string>
``` 
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528682/672c85b9-3262-d1cf-f087-59ed243c1f96.jpeg)

## Android
1.　`android/app/build.gradle`を開く
2.　`minSdkVersion`と書かれている行を見つけ出し、`minSdkVersion 21`に書き換える
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528682/90bc2f49-e022-48b5-843b-b457f9e602ad.jpeg)

# 2. cameraプラグインを使えるようにする。
1.　VSCodeの[ターミナル] > [新しいターミナル]をクリックし、ターミナルを出す。
2.　`flutter pub add camera`を実行する。
3.　色々と出てきて、最後に`Changed 7 dependencies!`が出てくる。`pubspec.yaml`を見て、`dependencies:`の所に`camera`が追加されていればOK。
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528682/cc04c710-1ace-ecd8-c5be-84dcbd572308.jpeg)


# 3. サンプルコードをコピペする
## `main.dart`に以下をコピペ

```Dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';

late List<CameraDescription> cameras;

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

  cameras = await availableCameras();
  runApp(CameraApp());
}

class CameraApp extends StatefulWidget {
  @override
  _CameraAppState 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(() {});
    });
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

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

## 4. `test\widget_test.dart`を修正
`test\widget_test.dart`にエラーが発生する（初期生成されていたMyApp()が消えたため）ので、`MyApp()`を`CameraApp()`に修正する。
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528682/56987162-f05d-871e-7ad3-1c6bb53354c1.jpeg)

多分、ここには`main.dart`のmain関数内の`runApp();`に入っている関数が来る。

# ※公式ドキュメントのエラーについて
**公式ドキュメントから変えているところを書いているので、興味なければ読み飛ばしてOKです。**

[公式ドキュメントのExample](https://pub.dev/packages/camera)をそのままコピペしたら、幾つかエラーが出たので修正しています。[「3. サンプルコードをコピペする」](サンプルコードをコピペする)に貼っているコードは修正後です。
以下に、元コード、エラー、修正後コードを置いておきます。

### 5行目
**元コード**
`List<CameraDescription> cameras;`

**エラー**

```
The non-nullable variable 'cameras' must be initialized.
Try adding an initializer expression.dart(not_initialized_non_nullable_variable)
```

**修正後コード**
`late List<CameraDescription> cameras;`

### 20行目
**元コード**
`CameraController controller;`

**エラー**

```
Non-nullable instance field 'controller' must be initialized.
Try adding an initializer expression, or a generative constructor that initializes it, or mark it 'late'.dar
```
**修正後コード**
`late CameraController controller;`

### 36行目（エラーではなく警告）
**元コード**
`controller?.dispose();`

**警告**

```
The receiver can't be null, so the null-aware operator '?.' is unnecessary.
Try replacing the operator '?.' with '.'.dart(invalid_null_aware_operator)
```

**修正後コード**
`controller.dispose();`

# デバッグして動かしてみる
ただただファインダー越しに見える景色を写すアプリが出来上がった。
![_20210814_222837[1].JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528682/2366a7b6-7c12-5164-1858-65f2dc791226.jpeg)

# オマケ程度のどうでもいい気付き
`main.dart`だと実行ボタンが表示されるのに、拡張子が`.dart`じゃないところは表示されない。
**`.dart`の時**
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528682/bc1d6c92-fb42-156b-3864-57bf50327800.jpeg)

**`.dart`じゃない時**
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528682/23916ba8-2f22-a54c-5a79-da549fb8e0b5.jpeg)

# 二日目終わり
本当は、カメラアプリを作るなど、もう少し進んだことをしたかったのですが、諸事情により時間が取れなかったこと、一気に色々としたらDartの意味を理解するのが追い付かないので、カメラ越しの景色を見るだけのアプリになりました。

本来作りたいものは、動画撮影を行うアプリなので、次は写真撮影アプリか、動画撮影アプリを作りたいなと思っています。

※追記
三日目は諸事情により、公式ドキュメントの続き（[1日目](https://qiita.com/ikeguma_Na/items/274223827b49f304b228)の続き）になりました。
三日目→[Flutter勉強記録3日目～公式ドキュメントのチュートリアル～](https://qiita.com/ikeguma_Na/items/ef2cda7644d2e35b10e9)