カメラを利用する

このページでは CameraX というカメラを使用するアプリを簡単に開発するためのライブラリを使用したサンプルを紹介します。

依存関係の追加

モジュールの build.gradle ファイルにCameraXの依存関係を追加します。

android {
    ...

    compileOptions {
        // Java8互換を指定
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    ...

    def camerax_version = "1.0.0-beta03"
    implementation "androidx.camera:camera-camera2:${camerax_version}"
    implementation "androidx.camera:camera-lifecycle:${camerax_version}"
    implementation "androidx.camera:camera-view:1.0.0-alpha10"
}

レイアウト設定

今回は activity_main.xml ファイルを編集してレイアウトを定義します。以下のコードで右図のような写真を撮るボタンと、まだ表示されていませんがカメラのプレビューを配置します。

   <Button
       android:id="@+id/camera_capture_button"
       android:layout_width="100dp"
       android:layout_height="100dp"
       android:layout_marginBottom="50dp"
       android:scaleType="fitCenter"
       android:text="Take Photo"
       app:layout_constraintLeft_toLeftOf="parent"
       app:layout_constraintRight_toRightOf="parent"
       app:layout_constraintBottom_toBottomOf="parent"
       android:elevation="2dp" />

   <androidx.camera.view.PreviewView
       android:id="@+id/viewFinder"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

権限のリクエスト

カメラを利用するにはユーザに権限をリクエストする必要があります。

まず、MainActivity.kt ファイルから編集していきます。

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

        // カメラ権限を確認 -> startCamera or 権限リクエスト
        if (allPermissionGranted()) {
            startCamera()
        } else {
            ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        }
    }

    // 権限リクエスト後の処理
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>,
        grantResults: IntArray
    ) {
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            // カメラ権限を確認 -> startCamera or エラーメッセージを表示
            if (allPermissionGranted()) {
                startCamera()
            } else {
                Toast.makeText(this, "Permissions not granted by the user.", Toast.LENGTH_SHORT)
                    .show()
                finish()
            }
        }
    }

    // スタブ
    private fun startCamera() {}

    // 必要な権限の確認
    private fun allPermissionGranted() = REQUIRED_PERMISSIONS.all {
        ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
    }

    companion object {
        // カメラ権限のリクエストコード
        private const val REQUEST_CODE_PERMISSIONS = 10
        // 必要な権限を定義
        private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
    }
}

次に、 AndroidManifest.xml ファイルに以下を追加します。

<!-- カメラを機能要件として宣言 -->
<uses-feature android:name="android.hardware.camera.any" />
<!-- カメラ権限の要求を宣言 -->
<uses-permission android:name="android.permission.CAMERA" />

まだ実際にカメラのプレビューを表示する関数は実装していませんが、この状態でアプリを起動すると、右図のように初回起動時にカメラ権限を要求するダイアログが表示されるはずです。

プレビューの実装

MainActivity.kt ファイルの startCamera関数を実装していきます。

class MainActivity : AppCompatActivity() {
    // 後でプレビューを保持させる
    private var preview: Preview? = null

    // 後でカメラを保持させる
    private var camera: Camera? = null

    ...

    // カメラプレビューの開始
    private fun startCamera() {
        // カメラの `lifecycle` を生成 (生存期間や競合を管理してくれる)
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)

        cameraProviderFuture.addListener(Runnable {
            // カメラの `lifecycle` を取得(=このプロセスにバインド)
            val cameraProvider = cameraProviderFuture.get()

            // プレビュー画面を生成
            preview = Preview.Builder().build()

            // バックカメラを選択
            val cameraSelector =
                CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()

            try {
                // 初期化
                cameraProvider.unbindAll()
                // カメラを割り当て
                camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview)
                // プレビューにカメラを設定
                preview?.setSurfaceProvider(viewFinder.createSurfaceProvider(camera?.cameraInfo))
            } catch (exc: Exception) {
                Log.e("MainActivity", "Use case binding failed", exc)
            }
        }, ContextCompat.getMainExecutor(this))
    }

}

これでアプリ上にカメラのプレビューが表示されるようになったはずです。

また、エミュレータ上のカメラは、Android Studio の ADV Manager の端末設定から変更することができ、仮想カメラを表示させることや、ホストマシン上のカメラを使用するように設定することもできます。右図は、ホストマシンのカメラを使用してアプリを起動した状態です。

文責 若園 (2020.6.12)