【ISSUE】Android, Kotlin + Camera API v2 でカメラ機能を実装する
2024年12月23日 17:28
この記事は高専 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 API 2を使って実装する記事が結構少ないように思われました。なので、最低限の実装で撮影ができるようになるまでを書いていきたいと思います。
とりあえず、Kotlin等のインストールは省略します。
Camera API v2はCamera API v1と比べて、かなり自由度は高くなりました。しかし、v1と違ってカメラのイベント関係をJava層まで落とし込んだインターフェスになっているので扱いは難しいです。
カメラを利用するために、Manifestにuses-permission
を追加します。カメラで撮影した写真を保存するために、ストレージへアクセスすることになるため、ストレージへのアクセスも許可します。
このrequestPermission
でカメラの利用許可を行わないと、まずカメラが使えません。なので、カメラ使用のリクエストを発行します。このrequestPermissionを呼び出す順番としては以下の通りで、openCamera
関数では、カメラ利用のための許可申請と、カメラを利用するための設定等を行います。そのため、この関数からカメラを使うためのいくつかの設定を行います。
使う変数としてはこんな感じですね。もっと簡略化できるのかもしれませんが、僕のではこうなりました^^;
カメラの処理はバックグラウンドで起動させるために、Thread処理を挟みます。カメラをバックグラウンドで起動させるための関数を作成して、onCreate
で呼び出します。backgroundThread
変数は後述するcreateCameraPreviewSession
関数内でのカメラ設定に利用します。
プレビューを表示するためのTextureView(previewView)にListenerを持たせます。これによってpreviewViewの変化をトリガーとして使うことができます。TextureViewが有効になったらプレビューをする準備をして、openCamera
をコールします
Camera API 2ではカメラを起動する際に、「カメラマネジャー」を使って、カメラを管理します。そのため、カメラマネジャーの設定、カメラIDの取得などを行います。
さて、openCamere
でパーミッションの確認が行われるわけですが、すでに許可されている時には、何事もなかったようにカメラが起動されますが、初回起動時などには、おなじみの許可ダイアログが表示されるようにします。
.setPositiveButton(button_string) { dialog, which -> }.show()
って書き方がどうも慣れない人が多いようです。{ _, _ -> }
となっていても問題はなくて、dialog, which
を使わないのであれば不要です。って言っているようなものだと思ってください。
カメラの許可も取れて、あとは起動するだけですが、起動する時にカメラに接続できているかどうかを確認する必要があります。なので、 manager.openCamera(camerId, stateCallback, null)
でカメラの状態を取得するためのコールバック関数を指定して、その関数の中で状態を把握します。もし、カメラになんらかの変化があれば、この関数にあるメソッドが呼ばれることになります。
createCameraPreviewSession
では、カメラから取得したデータをTextureViewにプレビューするための設定をします。setDefaultBufferSize
でpreviewView
の実機での表示サイズを取得して、textureのサイズを決めます。その後、カメラから取得したデータをtextureViewに投影します。
主に、カメラのデータをTextureViewにプレビューしている部分はここらへんになります。
追記: 2018/12/26 コメントより
Any app that declares the WRITE_EXTERNAL_STORAGE permission is implicitly granted this permission.
となっていて、WRITEもしくはREADの権限を付与すると、暗黙的にもう片方の権限も付与されるとのことです。そのため、片方の権限を付与するだけでいいようです。
カメラのデータを保存するために、ストレージアクセスをします。そのため、ストレージにアクセスするための権限を取得します。要領はカメラの時と同じです。以下のコードはパーミッションを確認する時に呼び出すものです。基本的には、アプリ起動時にすぐ呼び出す方がいいかと思います。が、ご自由にどうぞ。
requestStoragePermission
関数の内容は以下の通りです。カメラとの違いは、書き込みと読み込みの2つを行なっていることです。もしかしたら片方すればいいかと思うんですが、とりあえず2つしておきます。詳しい人教えてください...。
これでカメラのプレビューまで終わったわけですが、撮影しないと始まらないので、シャッターボタンを作成して押されたら表示してるプレビュー画像をファイルとして保存します。保存先はDocuments
になります。DIRECTORY_DOCUMENTS
の部分を変更すれば、別のディレクトリに対してフォルダを作成することができます(この場合だとcameraPreview
というフォルダを作成しています)
シャッターボタンが押されると、TextureViewの更新を停止して表示されている画像をファイルとして保存します。そして、再度TextureViewの更新を行うことでサイクルが完成します。
最低限必要な実装だけで、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]
診断を受けるとあなたの現在の業務委託単価を算出します。今後副業やフリーランスで単価を交渉する際の参考になります。また次の単価レンジに到達するためのヒントも確認できます。