Kanade Labo

かなで研究所

Android Studio カメラアプリ作成その9(カメラ表示4)

こんにちは かなで です。

続きです!

参考サイト

https://developer.android.com/training/camerax/preview?hl=ja

こちらの部分です。参考サイトからすると、これが最後です。

どこに入れるの!?(ほんと…なんでわかるんですか…

たぶんここで合ってます(笑

package net.kanalabo.cam

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.content.ContextCompat
import com.google.common.util.concurrent.ListenableFuture

//class MainActivity : AppCompatActivity() {
//    override fun onCreate(savedInstanceState: Bundle?) {
//        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)
//    }
//}

class MainActivity : AppCompatActivity() {
    private lateinit var cameraProviderFuture : ListenableFuture<ProcessCameraProvider>
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            val cameraProvider = cameraProviderFuture.get()
            bindPreview(cameraProvider)
        }, ContextCompat.getMainExecutor(this))
    }
    fun bindPreview(cameraProvider : ProcessCameraProvider) {
        var preview : Preview = Preview.Builder()
            .build()

        var cameraSelector : CameraSelector = CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK)
            .build()

        preview.setSurfaceProvider(previewView.getSurfaceProvider())

        var camera = cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, preview)
    }
}

まず、前回赤字だったbindePreviewですが、今追加したことで赤字でなくなりました。

問題ビューを見ると

こんだけありました。

一つずつ解決していきます。

といっても、上のUnresolved~は、インポートでいけそうです。

previewViewだけ、「インポート」という項目がありませんでした。

ちょっと長くなってきたので、import部分とそれ以外部分で画像を分けます。

赤字は「previewView」だけですね。

でここなんですが、以下記事でこんなことを言ってたのを覚えてますでしょうか。

こちらの記事で、previewViewをviewFinderに変えてますが、今残ってる赤字部分がこれと紐づけされている部分のようなので、こちらを変更します。

↑変更前  ↓変更後

はい。赤字じゃなくな…なくなってませんね(汗

失礼しました。

これだけじゃ治らないんでした(汗

というわけで何をするかというと、

val viewFinder: PreviewView = findViewById(R.id.viewFinder)

こちらの1行を追加します。

と、今書いて気づいたのですが、ここ↓も違う文字列でも大丈夫でした。

一旦言いたいことを整理しますと、

元々の公式サイトをもとに作成した場合、以下のようになるはずでした。

activity_main.xml
MainActivity.kt

「previewview」という文字列が散りばめられてて、とっても理解しにくかったんですが、同じ文字列だけど違う用途だと気付いて改変したのがこちらです。

activity_main.xml
MainActivity.kt

同じ色でくくっている者同士はリンクしてますが、違う色同士はリンクしてなくて、別にどんな名前でもOKだったんです。

これを踏まえて理解すると、

赤枠のPreviewViewは、そういう最初から決められた「関数」。プレビューをするために必要な関数でした。

青枠は、カメラプレビューを映す先のオブジェクトを表してたんですね。activity.main側でviewFinderという名前を決めて、MainActivity側で、viewFinderを探して、それに映すよ みたいな。そんな風にとらえました。

黄緑枠は、findeViewByIdで取得したviewFinderの画面をPreviewViewでプレビュー状態にして、それをkanadeFinderに格納して、次の行でそのkanadeFinderを使って…ん~書いててもよくわかりませんでした(汗 そんな感じです。

えっと…強行します。

先にやればよかったですが、「PreviewView」はクイックフィックスでインポートができたので、インポートは正解というルールに則りインポートします。

package net.kanalabo.cam

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.camera.core.CameraSelector
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner
import com.google.common.util.concurrent.ListenableFuture

//class MainActivity : AppCompatActivity() {
//    override fun onCreate(savedInstanceState: Bundle?) {
//        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)
//    }
//}

class MainActivity : AppCompatActivity() {
    private lateinit var cameraProviderFuture : ListenableFuture<ProcessCameraProvider>
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            val cameraProvider = cameraProviderFuture.get()
            bindPreview(cameraProvider)
        }, ContextCompat.getMainExecutor(this))
    }
    fun bindPreview(cameraProvider : ProcessCameraProvider) {
        var preview : Preview = Preview.Builder()
            .build()

        var cameraSelector : CameraSelector = CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK)
            .build()
        val kanadeFinder: PreviewView = findViewById(R.id.viewFinder)
        preview.setSurfaceProvider(kanadeFinder.getSurfaceProvider())

        var camera = cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, preview)
    }
}

あと残ってる問題ビューはこちら

----------------------------------------------------------------

上2行は、varよりvalの方がいいよと言ってるみたいです。

varは読み取り専用 valは書き換え可能 と理解しました。

varでいいんでしょうが、問題ビューを減らすためだけにvalに変えます。

「変えます」といっても、もちろん手作業じゃなく、クイックフィックスからですよ。

----------------------------------------------------------------

Variable 'camera' is never used

これは、cameraという変数を作ったのに、どこでも使ってないじゃん?という意味のようです。
プレビューまでには使いませんでしたが、きっとこの先使うことがあるんでしょう。
クリックフィックスすると消すことができますが、後で困りそうなので残しておきます。

----------------------------------------------------------------

関数 'bindPreview' は private である可能性があります

あ~そうでしたそうでしたprivateでした。(よくわかりませんが、Android Studioがそういうんでそうでしょう)

クイックフィックス後

----------------------------------------------------------------

プロパティアクセス構文の代わりに getter メソッドを使用

クイックフィックスするとこうなりました↓

「get」の文字がなくなりましたね。すいませんこの違いは分かってません。

----------------------------------------------------------------

そんなわけで問題ビューもいい感じになりました。

package net.kanalabo.cam

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.camera.core.CameraSelector
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner
import com.google.common.util.concurrent.ListenableFuture

//class MainActivity : AppCompatActivity() {
//    override fun onCreate(savedInstanceState: Bundle?) {
//        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)
//    }
//}

class MainActivity : AppCompatActivity() {
    private lateinit var cameraProviderFuture : ListenableFuture<ProcessCameraProvider>
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            val cameraProvider = cameraProviderFuture.get()
            bindPreview(cameraProvider)
        }, ContextCompat.getMainExecutor(this))
    }
    private fun bindPreview(cameraProvider : ProcessCameraProvider) {
        val preview : Preview = Preview.Builder()
            .build()

        val cameraSelector : CameraSelector = CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK)
            .build()
        val kanadeFinder: PreviewView = findViewById(R.id.viewFinder)
        preview.setSurfaceProvider(kanadeFinder.surfaceProvider)

        var camera = cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, preview)
    }
}

公式さんによれば、これでビルドするとプレビューがアプリに表示され、意図したとおりに動作するらしいです。

そんなうまくはいかないんですけどね!

次回へ続く。

最後までお読みいただきありがとうございました。
気になることがあったら、コメント頂けると嬉しいです。
自主学習も兼ねて記事にするかもしれません。

-AndroidStudio