LoginSignup
1
0

More than 3 years have passed since last update.

Androidカメラのプレビュー表示(Camera API + TextureView)

Last updated at Posted at 2020-10-19

前書き

前編ではAndroidカメラのプレビュー表示(Camera API + SurfaceView)について述べました。本編ではそれを踏まえて、Camera API + TextureViewの実装方法を紹介します。注意点は前編と同じで、TextureViewについての注意点は特にありません。

実装方法はCamera API + SurfaceViewのとかなり被る部分があるので、ここではあえて実装の差分のみ説明します。Androidカメラのプレビュー表示(Camera API + SurfaceView)と合わせてお読みいただければ幸いです。

実装

レイアウト

SurfaceViewをTextureViewに置き換えます。

main_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:keepScreenOn="true">

        <!-- SurfaceViewをTextureViewに置き換える -->
        <TextureView
            android:id="@+id/texture_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

カメラ起動

camera.setPreviewDisplay(surfaceHolder)をcamera.setPreviewTexture(surfaceTexture)に置き換えます。
surfaceViewをtextureViewに置き換えます。

MyActivity.kt
private fun openCamera() {
    val context = context ?: return
    val windowManager = activity?.windowManager ?: return

    // カメラIDを特定
    val cameraId = getCameraId(cameraType) ?: return

    // カメラを取得
    camera = Camera.open(cameraId)
    camera?.let { camera ->
        try {
            // camera.setPreviewDisplay(surfaceHolder)
            // カメラ出力先を指定
            // TextureViewに出力するので、setPreviewTexture()を使って、SurfaceTextureを設定
            camera.setPreviewTexture(surfaceTexture)
        } catch (ioException: IOException) {
            ioException.printStackTrace()
        }

        // [注意点]:端末の回転角度に合わせて、カメラの回転角度を設定
        camera.setDisplayOrientation(
                when (windowManager.defaultDisplay.rotation) {
                    Surface.ROTATION_0 -> 90
                    Surface.ROTATION_90 -> 0
                    Surface.ROTATION_180 -> 270
                    Surface.ROTATION_270 -> 180
                    else -> 0
                }
        )

        // カメラのパラメータを設定
        cameraParam = camera.parameters.apply {
            // プレビュー可能サイズを取得
            val size = supportedPreviewSizes.firstOrNull()
            size?.let { size ->
                // プレビューサイズを設定
                setPreviewSize(size.width, size.height)
            }
        }

        // カメラのパラメータを設定
        camera.parameters = camera.parameters.apply {
            val size = supportedPreviewSizes.firstOrNull()
            size?.let { size ->
                setPreviewSize(size.width, size.height)
            }
        }

        // カメラプレビューを開始
        camera.startPreview()

        // [注意点]:プレビューサイズに合わせて、TextureViewのサイズを調整する。
        // この処理が抜けると、プレビューのアスペクト比がおかしくなる可能性がある
        // surfaceViewをtextureViewに置き換える
        updateSurfaceSize(
            // binding.surfaceView,
            binding.textureView,
            camera.parameters.previewSize.width,
            camera.parameters.previewSize.height.
            surfaceWidth,
            surfaceHeight
        )
    }
}

TextureView

SurfaceViewをTextureViewに置き換えます。

MyActivity.kt
// SurfaceHolderをSurfaceTextureに置き換える
// private var surfaceHolder: SurfaceHolder? = null
private var surfaceTexture: SurfaceTexture? = null

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
): View? {
    binding = DataBindingUtil.inflate<MainFragmentBinding>(
            inflater,
            R.layout.main_fragment,
            container,
            false
    )

    // SurfaceViewをTextureViewに置き換える
    binding.textureView.surfaceTextureListener = object : TextureView.SurfaceTextureListener {

        override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
            surfaceTexture = surface
            surfaceWidth = width
            surfaceHeight = height
            checkAndAskPermission()
        }

        override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {
            surfaceWidth = width
            surfaceHeight = height
        }

        override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {

        }

        override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
            return false
        }
    }

    return binding.root
}

まとめ

ご覧になればおわかりだと思いますが、Camera API + SurfaceViewとCamera API + TextureViewの差分がかなり少ないです。しかもカメラ制御方法もほぼ一緒です。コツさえつかめば、SurfaceViewとTextureViewの双方向変換は簡単にできてしまいます。

GitHub

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0