20201021のAndroidに関する記事は3件です。

Associate Android Developer認定試験 スタディガイド翻訳

Associate Android Developer - Study Guide の翻訳

AAD認定試験スタディガイド翻訳のQiitaをちまっと投稿していたのですが、各々は短いので1記事にまとめました。

スタディガイド:
 0. Overview
 1. Android core
 2. User interface
 3. Data management
 4. Debugging
 5. Testing

Overview

Use the study guide to prepare for the Google Associate Android Developer Certification exam. This guide lists the competency areas and individual competencies against which you will be tested. There are also links to suggested web-based study resources. Note that these resources form only a small portion of what is available on the web, and we encourage you to do additional research.

スタディガイドを利用してGoogleアソシエイトAndroid開発者認定試験の準備をしましょう。このガイドは各能力分野と、あなたがテストされる個人技能を一覧にしています。また、Webベースの学習リソースへのリンクも設けてあります。これらのリソースはWebで手に入れることのできるリソースのほんの一部であることに注意し、ぜひとも追加の調査を行ってください。

Android core

Android is an operating system based on Linux and designed primarily for mobile devices. Android applications can be multitasking and are written in Java, Kotlin or C++.

AndroidはLinuxベースで主にモバイル端末向けにデザインされたOSです。Anroidアプリはマルチタスクで、Java、Kotlin、またはC++で書くことができます。

To prepare for the AAD certification exam, Android developers should:

  • Understand the architecture of the Android system
  • Be able to describe the basic building blocks of an Android app
  • Know how to build and run an Android app
  • Display simple messages in a popup using a Toast or a Snackbar
  • Be able to display a message outside your app's UI using Notifications
  • Understand how to localize an app
  • Be able to schedule a background task using JobScheduler

AAD(訳注:アソシエイトAndroid開発者) 認定試験に備え、Android開発者は下記を満たすようにします:

  • Androidシステムの構造を理解している
  • Androidアプリの基礎的な構成について説明できる
  • Androidアプリのビルド、実行方法を知っている
  • ToastSnackbarを用いたポップアップで簡単なメッセージを表示できる
  • Notificationsを使用してアプリUIの外側でメッセージを表示することができる
  • アプリのローカライズ方法を理解している
  • JobSchedulerを使用してバックグラウンド実行タスクをスケジュールできる

Resources

訳注:文中で触れられたリソースについてリンクが並んでます。リンク先ページは↑のURLリンクから本家で参照してください

Android Developers -> Toasts(※日本語)

  Android Developers : トーストの概要

Android Developers -> Snackbar(※英語)

  Android Developers : Snackbar

Android Developers -> Localize your app(※日本語)

  アプリをローカライズする

Android Developers -> Application fundamentals(※日本語)

  アプリの基礎

Android Developers -> Create a notification(※日本語)

  通知を作成する

Android Developers -> AndroidX overview(※日本語)

  AndroidXの概要

Android Developers -> Getting started with Jetpack(※日本語)

  Android Jetpackを使ってみる

Android Developers -> Android KTX (Kotlin)(※日本語)

  AndroidKTX(Android Jetpackの一部)

Codelabs -> Notifications(※英語)

Codelabs -> JobScheduler(※英語)

Codelabs -> WorkManager (Java)(※英語・なぜかリンク先はKotlinになっている)

Codelabs -> WorkManager (Kotlin)(※英語)

User Interface

The Android framework enables developers to create useful apps with effective user interfaces. Developers need to understand Android’s activities, views and layouts to create attractive UIs that maximize usability and the overall user experience.

Androidフレームワークにより、効果的なUIを持つ実用的なアプリを作成することができます。使いやすさと全体的なユーザエクスペリエンスを最大限にする魅力的なUIを作成するために、開発者はAndroidのアクティビティ、ビュー、そしてレイアウトを理解する必要があります。

To prepare for the AAD certification exam, Android developers should:

  • Understand the Android activity lifecycle
  • Be able to create an Activity that displays a Layout
  • Be able to construct a UI with ConstraintLayout
  • Understand how to create a custom View class and add it to a Layout
  • Know how to implement a custom app theme
  • Be able to add accessibility hooks to a custom View
  • Know how to apply content descriptions to views for accessibility
  • Understand how to display items in a RecyclerView
  • Be able to bind local data to a RecyclerView list using the Paging library
  • Know how to implement menu-based navigation
  • Understand how to implement drawer navigation

AAD認定試験のため、Android開発者には下記の要件が求められます:

  • Androidアクティビティのライフサイクルを理解している
  • レイアウトを表示するアクティビティを作成できる
  • ConstraintLayoutを使用したUIを構築することができる
  • カスタムビュークラスを作成し、レイアウトに追加する方法を理解している
  • カスタムアプリテーマの実装のしかたを知っている
  • カスタムビューにaccessibility hooks の適用することができる
  • アクセシビリティ向上のためのコンテンツラベルの追加方法を知っている
  • リサイクルビューで項目を表示する方法を知っている
  • ページングライブラリを使用してリサイクルビューにローカルのデータをバインドすることができる
  • メニューベースのナビゲーションの実装方法を知っている
  • ナビゲーションドロワーの実装方法を理解している

Resources

Android Developers -> Build a responsive UI with ConstraintLayout(※日本語)

Android Developers -> ConstraintLayout でレスポンシブ UI を作成する(Android Jetpackの一部)

Android Developers -> Create a list with RecyclerView(※日本語)

Android Developers -> リサイクルビューでリストを作成する

Android Developers -> Create a navigation drawer(※日本語)

Android Developers -> ナビゲーションドロワーを追加する

Android Developers -> Custom view components(※日本語)

Android Developers -> カスタムビュー コンポーネント

Android Developers -> Build more accessible custom views(※日本語)

Android Developers -> カスタムビューのユーザー補助機能を強化する

Android Developers -> Styles and themes(※日本語)

Android Developers -> スタイルとテーマ

Android Developers -> setContentDescription()(※英語)

Android Developers -> setContentDescription()

Android Developers -> Adding accessibility features to apps for blind and visually-impaired users(※英語動画)

Android Developers -> Youtube:目の不自由なユーザ向けの補助機能をアプリに追加する

Android Tool Time - Building interfaces with ConstraintLayout in AS(※英語動画)

Android Developers -> Youtube:ConstraintLayoutでインターフェースを作成する
 

Codelabs -> Activities and intents
Codelabs -> Your first interactive UI
Codelabs -> Themes and final touches
Codelabs -> RecyclerView
Codelabs -> Menus and pickers
Codelabs -> User navigation
Codelabs -> Material Components (Java)
Codelabs -> Material Components (Kotlin)
Codelabs -> Lifecycles
Codelabs -> Add user interactivity
Codelabs -> Constraint layout using the Layout Editor
Codelabs -> RecyclerView fundamentals (Kotlin)

Data management

Many Android apps store and retrieve user information that persists beyond the life of the app.

多くのアンドロイドアプリは、アプリのライフサイクルを超えて持続的にユーザー情報を収集します。
(訳注:アプリを起動していない時もバックグラウンドで持続的にデータ収集している、の意と解釈)

To prepare for the AAD certification exam, Android developers should:

  • Understand how to define data using Room entities
  • Be able to access Room database with data access object (DAO)
  • Know how to observe and respond to changing data using LiveData
  • Understand how to use a Repository to mediate data operations
  • Be able to read and parse raw resources or asset files
  • Be able to create persistent Preference data from user input
  • Understand how to change the behavior of the app based on user preferences

AAD認定試験の準備として、開発者は下記の要件を満たす必要があります:

  • Roomエンティティを使用してデータを定義する方法を理解している
  • RoomデータベースにDAOで接続することができる
  • LiveDataを使用してデータの変動を観測し対応する方法を知っている
  • データ操作の調整のためのRepositoryの使用方法を理解している
  • rawリソースやアセットファイルの読み込み、展開ができる
  • ユーザーの入力から持続的なプリファレンスデータを作成できる
  • ユーザーの好みに合わせアプリの挙動を変更する方法を理解している

Resources

Android Developers -> Shared preferences(※日本語)

Android Developers -> Key-Valueデータを保存する

Codelabs -> Room, LiveData and ViewModel(※英語)
Codelabs -> Repository(※英語)
Codelabs -> Drawables, styles, and themes(※英語)
Codelabs -> Shared preferences(※英語)
Codelabs -> App settings(※英語)
Codelabs -> ViewModel and ViewModelFactory(※英語)
Codelabs -> Room with a View (Java)(※英語)
Codelabs -> Room with a View (Kotlin)(※英語)

Debugging

Debugging is the process of isolating and removing defects in software code. By understanding the debugging tools in Android Studio, Android developers can create reliable and robust applications.

デバッグはソフトウェアのコードから欠陥を特定し取り除く過程です。Android Studioのデバッグツールを理解することで、Android開発者は信頼性が高く強固なアプリケーションを作成することができます。

To prepare for the AAD certification exam, Android developers should:

  • Understand the basic debugging techniques available in Android Studio
  • Know how to debug and fix issues with an app's functional behavior and usability
  • Be able to use the System Log to output debug information
  • Understand how to use breakpoints in Android Studio
  • Know how to inspect variables using Android Studio

AAD認定試験のため、開発者は次の要件を満たす必要があります:

  • Android Studioで利用できる基本的なデバッグテクニックを理解している
  • アプリの機能的な動作とユーザビリティの問題を検出し修正する方法を知っている
  • システムログを使用してデバッグ情報を出力できる
  • Android Studio内でのブレークポイントの使い方を理解している
  • Android Studioを使用して変数を検査する方法を知っている

Resources

Android Developers -> Debug your app(※日本語)

Android Developers -> アプリのデバッグ

Android Dev Fundamentals -> Write and view logs with Logcat(※日本語)

Android Developers -> logcat を使用してログを書き込み、表示する

Codelabs -> Android Studio debugger(※英語)
Codelabs -> Add log statements to your app(※英語)

Testing

Software testing is the process of executing a program with the intent of finding errors and abnormal or unexpected behavior. Testing and test-driven development (TDD) is a critically important step of the software development process for all Android developers. It helps to reduce defect rates in commercial and enterprise software.

ソフトウェアテストはエラー検出を目的とした異常な・予測していない操作をもって、プログラムを実行するプロセスです。テストとテスト駆動開発(TDD)はすべてのAndroid開発者にとって、ソフトウェア開発プロセスの中で非常に重要なステップとなります。これによりコンシューマ/エンタープライズソフトウェアの欠陥率を減らすことができます。

To prepare for the AAD certification exam, Android developers should:

  • Thoroughly understand the fundamentals of testing
  • Be able to write useful local JUnit tests
  • Understand the Espresso UI test framework
  • Know how to write useful automated Android tests

AAD認定試験のため、開発者は次の要件が必要となります:

  • テストの基本を徹底的に理解している
  • 実用的なローカルJUnitテストを書くことができる
  • Espresso UIテスト フレームワークを理解している
  • 実用的な自動化Androidテストの書き方がわかる

Resources

Android Developers -> Fundamentals of testing(※日本語)

Android Developers -> テストの基礎

Android Dev Fundamentals -> Automate UI tests(※日本語)

Android Developers -> ユーザー インターフェース テストを自動化する

Codelabs -> Unit tests(※英語)
Codelabs -> Android Testing -> Unit testing with JUnit and Mockito(※英語)
Codelabs -> Android Testing -> Espresso for UI testing(※英語)


スタディガイドは以上となります。
あくまで学ぶべき知識の概要や方針について記載されており、実際の知識は各Resourcesを参照しながら、手を動かして学ぶことになります。

Resourcesのリンク先の英語のみの記事も今後翻訳しようと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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

Camera2 APIによるカメラのプレビュー表示について

Androidカメラのプレビュー表示(Camera2 API + SurfaceView)に述べたように、Camera APIをCamera2 APIに変えると、カメラプレビューの実装が難しくなります。特にCamera2 APIには、Camera.Parameters.setPreviewDisplay()のようなプレビューサイズを設定するAPIがなく、Camera.setDisplayOrientationのようなカメラを回転させるAPIもないので、プレビューを正しく表示するのが難しいところです。

SurfaceViewを使う場合、画面の回転はやってくれるので、アスペクト比の調整のみを実装すればよいですが、TextureViewを使う場合、画面の回転はやってくれないので、そちらの実装もやらなければなりません。

本稿ではAndroidカメラのプレビュー表示(Camera2 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>

カメラ起動

surfaceHolderをsurfaceTextureに置き換えます。

MyActivity.kt
private val cameraDeviceStateCallback = object : CameraDevice.StateCallback() {
    override fun onOpened(device: CameraDevice) {
        cameraDevice = device

        cameraDevice?.let { cameraDevice ->
            val surfaceList: ArrayList<Surface> = arrayListOf()

            // surfaceHolderをsurfaceTextureに置き換えます。
            surfaceTexture?.let {
                surfaceList.add(Surface(it))
            }

            try {
                captureRequest = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
                    surfaceList.forEach {
                        addTarget(it)
                    }
                }.build()

                cameraDevice.createCaptureSession(
                        surfaceList,
                        cameraCaptureSessionStateCallback,
                        null
                )
            } catch (cameraAccessException: CameraAccessException) {
                cameraAccessException.printStackTrace()
            }
        }
    }

    override fun onDisconnected(device: CameraDevice) {
        cameraDevice = null
    }

    override fun onError(device: CameraDevice, error: Int) {
        cameraDevice = null
    }
}

Camera2 APIにCamera.Parameters.setPreviewDisplay()のようなプレビューサイズを直接的に設定するAPIがないが、TextureView.surfaceTexture.setDefaultBufferSize()でプレビューサイズを設定できます。そこで、まずCameraCharacteristicsからサポートサイズを取得します。

MyActivity.kt
private fun openCamera() {
    val context = context ?: return
    val cameraManager: CameraManager = cameraManager ?: return
    val cameraId = getCameraId() ?: return

    if (ActivityCompat.checkSelfPermission(
                    context,
                    Manifest.permission.CAMERA
            ) != PackageManager.PERMISSION_GRANTED
    ) {
        return
    }

    try {
        // CameraCharacteristicsからカメラのサポートサイズを取得します。
        cameraManager.getCameraCharacteristics(cameraId).get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)?.getOutputSizes(SurfaceTexture::class.java)?.getOrNull(0)?.let { size ->
            updateSurfaceSize(binding.textureView, size.width, size.height)
        }

        cameraManager.openCamera(cameraId, cameraDeviceStateCallback, null)
    } catch (cameraAccessException: CameraAccessException) {
        cameraAccessException.printStackTrace()
    }
}

TextureView

  1. SurfaceViewをTextureViewに置き換えます。
  2. [注意点]:onSurfaceTextureSizeChangedの中でプレビューサイズと回転角度を設定します。
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) {
            surfaceTexture = surface.apply {
                // [注意点]:ここでプレビューサイズと回転角度を設定する。
                updateSurfaceTexture(this, width, height)
            }
        }

        override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {

        }

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

    return binding.root
}

[注意点]:プレイビューサイズと回転角度の設定

  1. 幅と高さを決めます。端末が横の場合、幅=width、高さ=heightになります。端末が縦の場合、幅=height、高さ=widthになります。
  2. プレビューの中心点を軸に、プレビューを回転させ、かつ正しいアスペクト比にする行列を作ります。
  3. 行列をカメラに渡し、プレビューを調整します。
MyActivity.kt
private fun updateSurfaceTexture(surfaceTexture: SurfaceTexture, width: Int, height: Int) {
    // 端末が横の場合、幅=width、高さ=heightになります。
    var newWidth = width
    var newHeight = height

    // 端末が縦の場合、幅=height、高さ=widthになります。
    if (activity?.resources?.configuration?.orientation == Configuration.ORIENTATION_PORTRAIT) {
        newWidth = height
        newHeight = width
    }

    // setDefaultBufferSizeでプレビューサイズを設定する。
    surfaceTexture.setDefaultBufferSize(newWidth, newHeight)

    val transform = Matrix()
    val center = Point(newWidth / 2, newHeight / 2)

    // プレビューの中心点を軸に、プレビューを回転させる行列を作る
    when (activity?.windowManager?.defaultDisplay?.rotation) {
        Surface.ROTATION_90 -> {
            transform.postRotate(270.0f, center.x.toFloat(), center.y.toFloat())
        }
        Surface.ROTATION_180 -> {
            transform.postRotate(180.0f, center.x.toFloat(), center.y.toFloat())
        }
        Surface.ROTATION_270 -> {
            transform.postRotate(90.0f, center.x.toFloat(), center.y.toFloat())
        }
    }

    // 正しいアスペクト比に戻す
    when (activity?.windowManager?.defaultDisplay?.rotation) {
        Surface.ROTATION_90, Surface.ROTATION_270 -> {
            transform.postScale(newWidth.toFloat() / newHeight.toFloat() * newWidth.toFloat() / newHeight.toFloat(),
                    1.0f,
                    center.x.toFloat(),
                    center.y.toFloat())
        }
    }

    // カメラに行列を渡し、プレビューを調整する
    binding.textureView.setTransform(transform)

    surfaceWidth = width
    surfaceHeight = height
}

まとめ

Camera2 API + TextureViewの方法は、Camera2 API + SurfaceView方法とCamera API + TextureView方法よりも自由度が高いですが、プレビュー表示処理がだいぶ複雑になります。
個人的には仕様制限がないのプレビュー表示について
Androidカメラのプレビュー表示(Camera2 API + SurfaceView)に述べたように、Camera APIをCamera2 APIに変えると、カメラプレビューの実装が難しくなります。特にCamera2 APIには、Camera.Parameters.setPreviewDisplay()のようなプレビューサイズを設定するAPIがなく、Camera.setDisplayOrientationのようなカメラを回転させるAPIもないので、プレビューを正しく表示するのが難しいところです。

SurfaceViewを使う場合、画面の回転はやってくれるので、アスペクト比の調整のみを実装すればよいですが、TextureViewを使う場合、画面の回転はやってくれないので、そちらの実装もやらなければなりません。

本稿ではAndroidカメラのプレビュー表示(Camera2 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>

カメラ起動

surfaceHolderをsurfaceTextureに置き換えます。

MyActivity.kt
private val cameraDeviceStateCallback = object : CameraDevice.StateCallback() {
    override fun onOpened(device: CameraDevice) {
        cameraDevice = device

        cameraDevice?.let { cameraDevice ->
            val surfaceList: ArrayList<Surface> = arrayListOf()

            // surfaceHolderをsurfaceTextureに置き換えます。
            surfaceTexture?.let {
                surfaceList.add(Surface(it))
            }

            try {
                captureRequest = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
                    surfaceList.forEach {
                        addTarget(it)
                    }
                }.build()

                cameraDevice.createCaptureSession(
                        surfaceList,
                        cameraCaptureSessionStateCallback,
                        null
                )
            } catch (cameraAccessException: CameraAccessException) {
                cameraAccessException.printStackTrace()
            }
        }
    }

    override fun onDisconnected(device: CameraDevice) {
        cameraDevice = null
    }

    override fun onError(device: CameraDevice, error: Int) {
        cameraDevice = null
    }
}

Camera2 APIにCamera.Parameters.setPreviewDisplay()のようなプレビューサイズを直接的に設定するAPIがないが、TextureView.surfaceTexture.setDefaultBufferSize()でプレビューサイズを設定できます。そこで、まずCameraCharacteristicsからサポートサイズを取得します。

MyActivity.kt
private fun openCamera() {
    val context = context ?: return
    val cameraManager: CameraManager = cameraManager ?: return
    val cameraId = getCameraId() ?: return

    if (ActivityCompat.checkSelfPermission(
                    context,
                    Manifest.permission.CAMERA
            ) != PackageManager.PERMISSION_GRANTED
    ) {
        return
    }

    try {
        // CameraCharacteristicsからカメラのサポートサイズを取得します。
        cameraManager.getCameraCharacteristics(cameraId).get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)?.getOutputSizes(SurfaceTexture::class.java)?.getOrNull(0)?.let { size ->
            updateSurfaceSize(binding.textureView, size.width, size.height)
        }

        cameraManager.openCamera(cameraId, cameraDeviceStateCallback, null)
    } catch (cameraAccessException: CameraAccessException) {
        cameraAccessException.printStackTrace()
    }
}

TextureView

  1. SurfaceViewをTextureViewに置き換えます。
  2. [注意点]:onSurfaceTextureSizeChangedの中でプレビューサイズと回転角度を設定します。
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) {
            surfaceTexture = surface.apply {
                // [注意点]:ここでプレビューサイズと回転角度を設定する。
                updateSurfaceTexture(this, width, height)
            }
        }

        override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {

        }

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

    return binding.root
}

[注意点]:プレイビューサイズと回転角度の設定

  1. 幅と高さを決めます。端末が横の場合、幅=width、高さ=heightになります。端末が縦の場合、幅=height、高さ=widthになります。
  2. プレビューの中心点を軸に、プレビューを回転させ、かつ正しいアスペクト比にする行列を作ります。
  3. 行列をカメラに渡し、プレビューを調整します。
MyActivity.kt
private fun updateSurfaceTexture(surfaceTexture: SurfaceTexture, width: Int, height: Int) {
    // 端末が横の場合、幅=width、高さ=heightになります。
    var newWidth = width
    var newHeight = height

    // 端末が縦の場合、幅=height、高さ=widthになります。
    if (activity?.resources?.configuration?.orientation == Configuration.ORIENTATION_PORTRAIT) {
        newWidth = height
        newHeight = width
    }

    // setDefaultBufferSizeでプレビューサイズを設定する。
    surfaceTexture.setDefaultBufferSize(newWidth, newHeight)

    val transform = Matrix()
    val center = Point(newWidth / 2, newHeight / 2)

    // プレビューの中心点を軸に、プレビューを回転させる行列を作る
    when (activity?.windowManager?.defaultDisplay?.rotation) {
        Surface.ROTATION_90 -> {
            transform.postRotate(270.0f, center.x.toFloat(), center.y.toFloat())
        }
        Surface.ROTATION_180 -> {
            transform.postRotate(180.0f, center.x.toFloat(), center.y.toFloat())
        }
        Surface.ROTATION_270 -> {
            transform.postRotate(90.0f, center.x.toFloat(), center.y.toFloat())
        }
    }

    // 正しいアスペクト比に戻す
    when (activity?.windowManager?.defaultDisplay?.rotation) {
        Surface.ROTATION_90, Surface.ROTATION_270 -> {
            transform.postScale(newWidth.toFloat() / newHeight.toFloat() * newWidth.toFloat() / newHeight.toFloat(),
                    1.0f,
                    center.x.toFloat(),
                    center.y.toFloat())
        }
    }

    // カメラに行列を渡し、プレビューを調整する
    binding.textureView.setTransform(transform)

    surfaceWidth = width
    surfaceHeight = height
}

まとめ

Camera2 API + TextureView方法は、Camera2 API + SurfaceView方法とCamera API + TextureView方法よりも自由度が高いですが、プレビュー表示処理がだいぶ複雑になります。また、Camera2 APIの使い方もCamera APIより複雑ですし、カメラのプレビューサイズを直接に指定するAPIもありません。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Android color配色

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む