【ISSUE】Android, Kotlin + Camera API v2 でカメラ機能を実装する

0

2024年12月23日 17:28

高専 Advent Calendar 2018 2日目

この記事は高専 Advent Calendar 2018の2日目の記事(のコピー)です。実態はこっちです。

http://nomunomu.hateblo.jp/entry/2018/12/02/000019

前日の記事はTorikaraHNMさんの英語キーボードを使い始めた話です。

予定では、量子コンピュータに関して書く予定だったのですが、何を思ったか先に書いてしまったという失態...。

http://nomunomu.hateblo.jp/entry/2018/09/07/012803

http://nomunomu.hateblo.jp/entry/2018/11/09/023652

なので、題目を変更しました...。

Kotlin + Camera v2

タイトルにもあるように、KotlinでCamera API 2を使って実装する記事が結構少ないように思われました。なので、最低限の実装で撮影ができるようになるまでを書いていきたいと思います。

とりあえず、Kotlin等のインストールは省略します。

Camera API v2

Camera API v2はCamera API v1と比べて、かなり自由度は高くなりました。しかし、v1と違ってカメラのイベント関係をJava層まで落とし込んだインターフェスになっているので扱いは難しいです。

パーミッションの追加

カメラを利用するために、Manifestにuses-permissionを追加します。カメラで撮影した写真を保存するために、ストレージへアクセスすることになるため、ストレージへのアクセスも許可します。

img

requestPermission

このrequestPermissionでカメラの利用許可を行わないと、まずカメラが使えません。なので、カメラ使用のリクエストを発行します。このrequestPermissionを呼び出す順番としては以下の通りで、openCamera関数では、カメラ利用のための許可申請と、カメラを利用するための設定等を行います。そのため、この関数からカメラを使うためのいくつかの設定を行います。

img

使う変数としてはこんな感じですね。もっと簡略化できるのかもしれませんが、僕のではこうなりました^^;

img

backgroundThread

カメラの処理はバックグラウンドで起動させるために、Thread処理を挟みます。カメラをバックグラウンドで起動させるための関数を作成して、onCreateで呼び出します。backgroundThread変数は後述するcreateCameraPreviewSession関数内でのカメラ設定に利用します。

img

surfaceTextureListener

プレビューを表示するためのTextureView(previewView)にListenerを持たせます。これによってpreviewViewの変化をトリガーとして使うことができます。TextureViewが有効になったらプレビューをする準備をして、openCameraをコールします

img

openCamera

Camera API 2ではカメラを起動する際に、「カメラマネジャー」を使って、カメラを管理します。そのため、カメラマネジャーの設定、カメラIDの取得などを行います。

img

requestPermission

さて、openCamereでパーミッションの確認が行われるわけですが、すでに許可されている時には、何事もなかったようにカメラが起動されますが、初回起動時などには、おなじみの許可ダイアログが表示されるようにします。

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f33343438382f32303466316232632d623732362d363466612d346235662d3639343333386565613136372e706e67.png

img

.setPositiveButton(button_string) { dialog, which -> }.show()って書き方がどうも慣れない人が多いようです。{ _, _ -> }となっていても問題はなくて、dialog, whichを使わないのであれば不要です。って言っているようなものだと思ってください。

stateCallback

カメラの許可も取れて、あとは起動するだけですが、起動する時にカメラに接続できているかどうかを確認する必要があります。なので、 manager.openCamera(camerId, stateCallback, null)でカメラの状態を取得するためのコールバック関数を指定して、その関数の中で状態を把握します。もし、カメラになんらかの変化があれば、この関数にあるメソッドが呼ばれることになります。

img

createCameraPreviewSession

createCameraPreviewSessionでは、カメラから取得したデータをTextureViewにプレビューするための設定をします。setDefaultBufferSizepreviewViewの実機での表示サイズを取得して、textureのサイズを決めます。その後、カメラから取得したデータをtextureViewに投影します。

img
主に、カメラのデータをTextureViewにプレビューしている部分はここらへんになります。

img

requestStoragePermission

追記: 2018/12/26 コメントより

Any app that declares the WRITE_EXTERNAL_STORAGE permission is implicitly granted this permission.

となっていて、WRITEもしくはREADの権限を付与すると、暗黙的にもう片方の権限も付与されるとのことです。そのため、片方の権限を付与するだけでいいようです。

カメラのデータを保存するために、ストレージアクセスをします。そのため、ストレージにアクセスするための権限を取得します。要領はカメラの時と同じです。以下のコードはパーミッションを確認する時に呼び出すものです。基本的には、アプリ起動時にすぐ呼び出す方がいいかと思います。が、ご自由にどうぞ。

img

requestStoragePermission関数の内容は以下の通りです。カメラとの違いは、書き込みと読み込みの2つを行なっていることです。もしかしたら片方すればいいかと思うんですが、とりあえず2つしておきます。詳しい人教えてください...。

img

シャッターボタンへのアクション

これでカメラのプレビューまで終わったわけですが、撮影しないと始まらないので、シャッターボタンを作成して押されたら表示してるプレビュー画像をファイルとして保存します。保存先はDocumentsになります。DIRECTORY_DOCUMENTSの部分を変更すれば、別のディレクトリに対してフォルダを作成することができます(この場合だとcameraPreviewというフォルダを作成しています)
シャッターボタンが押されると、TextureViewの更新を停止して表示されている画像をファイルとして保存します。そして、再度TextureViewの更新を行うことでサイクルが完成します。

img

まとめ

最低限必要な実装だけで、Camera API 2をKotlinで使うことができるようになったはずです。(これが最小限かどうかはわかりませんが...。)ただし、画面の回転でTextureViewの変更などは考えていません。画面の回転等はちょっと面倒なんですよねー。端末の物理的回転とシステム上で認識されている回転とがずれているので、そこを補助する必要があります...。回転とか、カメラのいろいろに関しては、こちらのソースを参考にしてください。こちらのOSSは自分が一昔前に関わらさせていただいていたものです。更新はされてないようですが。。。Javaで書かれているんですが、カメラ部分などは参考にできるかと(結構面倒な処理とかもして大変でした...。)

https://github.com/e-fas/tabijimanOSS-Android

実はiPhone版もあったりするので、みるだけでも損はないと思います!笑

https://github.com/e-fas/tabijimanOSS-iOS

ソースコード

ソースコードですが、現在開発中のシステムで、これを構築していたので全体の公開はすることができません。そのため、コメントやTwitterなどでリクエストがあれば、詳しく説明 or 一部コードの提供をさせていただきます!!!

次の記事

次の「高専 Advent Calendar 2018」記事は、ykbr_さんの「ykbr__aiの話」です。ぜひそちらもみてみてください!!

https://adventar.org/calendars/2979
[cv:issue_marketplace_engineer]

0

診断を受けるとあなたの現在の業務委託単価を算出します。今後副業やフリーランスで単価を交渉する際の参考になります。また次の単価レンジに到達するためのヒントも確認できます。