Flutterでカメラを使う

最近 Release Preview 1 がリリースされた Google 製クロスプラットフォーム環境 Flutter。

一度触ってみて、本ブログでも導入部分を紹介しました。

もう少し実際のアプリで使うであろう機能について使い方などを踏み込んで調べてみました。

今回はカメラになります。

なお、今回利用している Camera プラグインはまだ開発中とのことなので、今後 API など変わる可能性はあります。

今回作ったアプリ

カメラのプレビュー画面を表示し、ボタンをタップするとカメラを使って撮影をするという単純なアプリです。

ソースコードは GitHubにあげてます。

カメラの処理については capture.dart でやってます。

実装内容

1. Flutter 環境の構築

Flutter 環境の構築方法に関しては以前書いた記事を参考にしていただければ。

2. Camera プラグインの導入

カメラを使うために、公式で提供されている camera プラグインを導入します。

Flutter のプロジェクト内にある pubspec.yaml の dependencies の項目に camera: を追加します。

また、撮影した画像の出力先のファイルパスを取得するために、path_provider プラグインも導入しておきます。

追加したら、Android Studio、IntelliJ を使っている方は右上に表示される Packages get でプラグインをダウンロードします。

コンソールで行う場合は、flutter packages get を実行します。

3. プロジェクトでカメラを使えるようにする

iOS、Android のそれぞれでカメラを使う設定を追加します。

iOS の場合は Info.plist 下記キーを設定します。

Android の場合、最小SDKで 21 を指定するようにします。camera プラグインで SDK 21 で提供されている CameraDevice を使っているためです。

android/app/build.gradle

を指定します。

Android の “android.permission.CAMERA” パーミッションの指定はアプリの方で行わなくても良いみたいです。プラグインの方で指定されているみたいですね。

4. カメラ制御部の初期化

ここから実際のソースコードの内容に触れていきます。

GitHub の capture.dart も合わせて参照ください。

まずは availableCameras で利用できるカメラの情報を取得します。

camera プラグインで利用できる関数の多くは非同期関数なので、then や async/await の書き方を使って結果を取得します。

availableCameras で取得できるのは List<CameraDescription> です。

今の端末の多くはリアカメラとフロントカメラのように複数のカメラを持っていますので、利用できるカメラの情報もリストで返ってくるようになっています。

CameraDescription にはカメラレンズの方向(フロントかリアか)が含まれていますので、それをもとに使うカメラを決めます。今回はリアカメラを使うことにしました。

使うカメラが決まったら、その CameraDescription を指定して CameraController のインスタンスを作成し、initialize メソッドを呼び出します。

コンストラクタの二つ目の引数はプレビュー画面の解像度をどの程度のものにするかという目安です。

initialize 時に、Android アプリではおなじみのカメラの使用の許可を求めるダイアログが出ます。このあたりをライブラリでやってくれるのは楽で良いですね。

以降の処理はすべて作成した CameraController のインスタンスに対して行います。

5. プレビュー用 Widget の作成

カメラのプレビュー用に CameraPreview という Widget がプラグインの方で用意されていますので、それを作成して画面に配置します。

カメラ画像のアスペクト比が controller.value.aspectRatio で取得できますので、プレビュー画面もその比率で表示するよう AspectRatio Widget を使っています。

6. 撮影

撮影は CameraController.takePicture で行います。引数は画像の保存先のファイルパスです。

今回は path_provider プラグインで取得できる getApplicationDocumentsDirectory() を使い、アプリケーション内ごとの保存領域に保存するようにしました。

端末のギャラリー(iOSのカメラロール)に保存する方法を探して見たのですが、今のところ自分でプラグインを書くしか無さそう。気が向いたら作ってみます。

トラブルシューティング

基本は camera プラグインを使って実装すればよいという話だけなのですが、わたしの持っている端末の中に、下記エラーを出力してリアカメラが使えない端末がありました。(Zenfone3 Android 7.0)

デバイスで対応していない解像度とか保存形式を指定したときに出るエラーだそう。

camera プラグインではプレビュー用と画像保存用で 2つのサーフェイスを出力しているのですが、複数サーフェイスに対して出力するときは単体とは別の解像度制限があるらしく、それが考慮されてないように思いました。

一応そのあたりを改造版 camera プラグインを GitHub にあげました。もし同じエラーが出てしまったら試してみてください。

下記のように pubspec.yaml でプラグインのリポジトリを指定すると使えます。コードの方での変更は必要ありません。

PR もしてみた けど、まだ受け入れられるかはわかりません。

おわりに

どうにか当初の目的のカメラで撮影する部分まではできたのですが、プラグインの機能がもうちょっと充実してほしいところではあります。(ギャラリーに保存するところとか)

今回少しプラグインをいじってみたりしたのですがプラグインの実装自体は割とわかりやすい感じでした。公開されてるプラグインでどうにもならなければ、自分で Kotlin/Swift で書けばいっかーって感じがしました。

正直 Android も iOS も、UI 部分の実装が一番時間がかかると思っているので、そのあたりだけでも Flutter で共通コードになればありがたいです。

またアプリで使いそうな機能の実装方法調べたら書いていきます。


最後まで読んでいただきありがとうございます。 このブログを「いいな」と感じていただけましたら、Twiter にてフォローいただけるとうれしいです。ブログ更新情報などもお届けします。



この記事をシェアする






りゅーた
フリーランスのエンジニアしてます。Android、iOS アプリの開発、対向サーバの開発、C/C++のライブラリ開発が現在のメイン。趣味はテニス。3児の父。 もっと詳しく

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA