Ciptakan pengalaman kamera Anda

1. Sebelum memulai

Apa yang istimewa dari perangkat foldable?

Perangkat foldable adalah inovasi yang hanya terjadi sekali dalam satu generasi. Perangkat ini memberikan pengalaman unik, dan disertai peluang unik untuk menyenangkan pengguna Anda dengan fitur yang berbeda seperti UI dalam mode di atas meja untuk penggunaan handsfree.

Prasyarat

  • Pengetahuan dasar tentang pengembangan aplikasi Android
  • Pengetahuan dasar framework Injeksi Dependensi dengan Hilt

Yang akan Anda bangun

Dalam codelab ini, Anda membangun aplikasi kamera dengan tata letak yang dioptimalkan untuk perangkat foldable.

Screenshot aplikasi yang sedang berjalan

Anda mulai dengan aplikasi kamera dasar yang tidak bereaksi terhadap postur perangkat apa pun atau memanfaatkan kamera belakang yang lebih baik untuk mendapatkan hasil selfie yang lebih sempurna. Anda memperbarui kode sumber untuk memindahkan pratinjau ke layar yang lebih kecil saat perangkat dibentangkan dan bereaksi terhadap ponsel yang diatur dalam mode di atas meja.

Meskipun aplikasi kamera adalah kasus penggunaan yang paling nyaman untuk API ini, kedua fitur yang Anda pelajari dalam codelab ini dapat diterapkan ke aplikasi apa pun.

Yang akan Anda pelajari

  • Cara menggunakan Jetpack Window Manager untuk bereaksi terhadap perubahan postur
  • Cara memindahkan aplikasi Anda ke layar perangkat foldable yang lebih kecil

Yang akan Anda butuhkan

  • Versi terbaru Android Studio
  • Perangkat foldable atau emulator perangkat foldable

2. Memulai persiapan

Mendapatkan kode awal

  1. Jika sudah menginstal Git, Anda cukup menjalankan perintah di bawah ini. Untuk memeriksa apakah Git sudah diinstal atau belum, ketik git --version di terminal atau command line dan pastikan Git dijalankan dengan benar.
git clone https://github.com/android/large-screen-codelabs.git
  1. Opsional: Jika tidak memiliki Git, Anda dapat mengklik tombol berikut untuk mendownload semua kode untuk codelab ini:

Membuka modul pertama

  • Di Android Studio, buka modul pertama di /step1.

Screenshot Android Studio yang menampilkan kode yang terkait dengan codelab ini

Jika Anda diminta untuk menggunakan versi Gradle terbaru, lanjutkan lalu update.

3. Menjalankan dan mengamati

  1. Jalankan kode pada modul step1.

Seperti yang Anda lihat, ini adalah aplikasi kamera sederhana. Anda dapat beralih antara kamera depan dan belakang serta menyesuaikan rasio aspek. Namun, tombol pertama dari kiri saat ini tidak memiliki fungsi apa pun—tetapi ini akan menjadi titik masuk untuk mode Selfie Belakang.

Screenshot aplikasi dengan sorotan pada ikon mode Selfie Belakang

  1. Sekarang, coba letakkan perangkat dalam posisi setengah terbuka, di mana engselnya tidak sepenuhnya lurus atau tertutup, tetapi membentuk sudut 90 derajat.

Seperti yang Anda lihat, aplikasi tidak merespons postur perangkat yang berbeda dan tata letaknya juga tidak berubah, sehingga engsel berada di tengah jendela bidik.

4. Mempelajari Jetpack WindowManager

Library Jetpack WindowManager membantu developer aplikasi membuat pengalaman yang dioptimalkan untuk perangkat foldable. Library ini berisi class FoldingFeature yang menjelaskan lipatan di layar yang fleksibel atau engsel di antara dua panel layar fisik. API-nya memberikan akses ke informasi penting yang berkaitan dengan perangkat:

Class FoldingFeature berisi informasi tambahan, seperti occlusionType() atau isSeparating(), tetapi codelabe ini tidak membahasnya secara mendalam.

Mulai versi 1.1.0-beta01, library ini menggunakan WindowAreaController, sebuah API yang memungkinkan Mode Tampilan Belakang memindahkan jendela saat ini ke tampilan yang sejajar dengan kamera belakang, yang sangat cocok untuk berfoto selfie menggunakan kamera belakang serta banyak kasus penggunaan lainnya.

Menambahkan dependensi

  • Untuk menggunakan Jetpack WindowManager di aplikasi Anda, tambahkan dependensi berikut ke file build.gradle level modul Anda:

step1/build.gradle

def work_version = '1.1.0-beta01'
implementation "androidx.window:window:$work_version"
implementation "androidx.window:window-java:$work_version"
implementation "androidx.window:window-core:$work_version"

Sekarang Anda dapat mengakses class FoldingFeature dan WindowAreaController di aplikasi Anda. Gunakan kedua class tersebut untuk membuat pengalaman kamera terbaik pada perangkat foldable.

5. Mengimplementasikan mode Selfie Belakang

Mulai dengan mode Tampilan Belakang. API yang memungkinkan mode ini adalah WindowAreaControllerJavaAdapter, yang memerlukan Executor dan menampilkan WindowAreaSession yang menyimpan keadaan saat ini. Class WindowAreaSession ini harus dipertahankan saat Activity Anda dihancurkan dan dibuat ulang. Oleh karena itu, Anda perlu menyimpannya di dalam ViewModel agar class ini tersimpan dengan aman saat terjadi perubahan konfigurasi.

  1. Deklarasikan variabel ini di MainActivity Anda:

step1/MainActivity.kt

private lateinit var windowAreaController: WindowAreaControllerJavaAdapter
private lateinit var displayExecutor: Executor
  1. Dan inisialisasi variabel tersebut dalam metode onCreate():

step1/MainActivity.kt

windowInfoTracker = WindowInfoTracker.getOrCreate(this)
displayExecutor = ContextCompat.getMainExecutor(this)
windowAreaController = WindowAreaControllerJavaAdapter(WindowAreaController.getOrCreate())

Sekarang Activity Anda siap untuk memindahkan konten ke layar yang lebih kecil, tetapi Anda perlu menyimpan sesi tersebut.

  1. Untuk menyimpan sesi, buka CameraViewModel dan deklarasikan variabel ini di dalamnya:

step1/CameraViewModel.kt

var rearDisplaySession: WindowAreaSession? = null
        private set

rearDisplaySession harus bersifat variabel, karena kode ini berubah setiap kali Anda membuatnya. Namun, pastikan kode tidak dapat diperbarui dari luar karena Anda sekarang membuat metode yang memperbaruinya kapan pun diperlukan.

  1. Tempelkan kode ini di dalam CameraViewModel:

step1/CameraViewModel.kt

fun updateSession(newSession: WindowAreaSession? = null) {
        rearDisplaySession = newSession
}

Metode ini dipanggil setiap kali kode Anda perlu memperbarui sesi, dan sebaiknya ini dienkapsulasi dalam satu titik akses.

Rear Display API bekerja dengan pendekatan pemroses: saat Anda meminta untuk memindahkan konten ke layar yang lebih kecil, Anda memulai sesi yang dihasilkan melalui metode onSessionStarted() pemroses. Jika ingin kembali ke layar dalam (dan lebih besar), tutup sesi, dan Anda mendapatkan konfirmasi dalam metode onSessionEnded(). Anda memanfaatkan metode ini untuk memperbarui rearDisplaySession di dalam CameraViewModel. Untuk membuat pemroses seperti itu, Anda perlu mengimplementasikan antarmuka WindowAreaSessionCallback.

  1. Ubah deklarasi MainActivity agar mengimplementasikan antarmuka WindowAreaSessionCallback:

step1/MainActivity.kt

class MainActivity : AppCompatActivity(), WindowAreaSessionCallback

Sekarang, terapkan metode onSessionStarted dan onSessionEnded di dalam MainActivity. Untuk metode pertama, sebaiknya simpan WindowAreaSession, dan dalam metode kedua, reset ke null. Hal ini sangat berguna karena keberadaan WindowAreaSession memungkinkan Anda memutuskan apakah akan memulai sesi atau menutup sesi yang sudah ada.

step1/MainActivity.kt

override fun onSessionEnded() {
    viewModel.updateSession(null)
}

override fun onSessionStarted(session: WindowAreaSession) {
    viewModel.updateSession(session)
}
  1. Di dalam file MainActivity.kt, tulis kode terakhir yang diperlukan agar API ini berfungsi:

step1/MainActivity.kt

private fun startRearDisplayMode() {
   if (viewModel.rearDisplaySession != null) {
      viewModel.rearDisplaySession?.close()
   } else {
      windowAreaController.startRearDisplayModeSession(
         this,
         displayExecutor,
         this
      )
   }
}

Seperti disebutkan sebelumnya, untuk memahami tindakan apa yang harus diambil, Anda perlu memeriksa keberadaan rearDisplaySession di dalam CameraViewModel: jika yang ditampilkan bukan null, berarti sesi sudah berlangsung, sehingga sesi tersebut ditutup. Di sisi lain, jika yang ditampilkan adalah null, Anda menggunakan windowAreaController untuk memulai sesi baru, dengan meneruskan Activity dua kali. Yang pertama digunakan sebagai Context dan yang kedua sebagai pemroses WindowAreaSessionCallback.

  1. Sekarang, bangun dan jalankan aplikasi. Jika Anda kemudian membentangkan perangkat dan mengetuk tombol tampilan belakang, Anda akan dihadapkan pada pesan seperti ini:

Screenshot perintah pengguna yang menunjukkan saat Mode Tampilan Belakang dimulai.

  1. Klik Beralih layar sekarang dan lihat konten Anda dipindahkan ke layar luar.

6. Mengimplementasikan Mode di atas meja

Sekarang saatnya membuat aplikasi Anda fold-aware: pindahkan konten ke samping atau ke atas engsel perangkat berdasarkan orientasi lipatan. Untuk melakukannya, Anda akan bertindak di dalam FoldingStateActor sehingga kode Anda dipisahkan dari Activity agar lebih mudah dibaca.

Bagian inti dari API ini terdiri dari antarmuka WindowInfoTracker, yang dibuat dengan metode statis yang memerlukan Activity:

step1/CameraCodelabDependencies.kt

@Provides
fun provideWindowInfoTracker(activity: Activity) =
        WindowInfoTracker.getOrCreate(activity)

Anda tidak perlu menulis kode ini karena sudah ada, tetapi akan berguna untuk memahami bagaimana WindowInfoTracker dibangun.

  1. Untuk memproses perubahan jendela apa pun, proses perubahan ini dalam metode onResume() dari Activity Anda:

step1/MainActivity.kt

lifecycleScope.launch {
    foldingStateActor.checkFoldingState(
         this@MainActivity,
         binding.viewFinder
    )
}
  1. Sekarang, buka file FoldingStateActor, karena sudah saatnya memasukkan metode checkFoldingState().

Seperti yang sudah Anda lihat, metode ini berjalan dalam fase RESUMED dari Activity Anda, dan memanfaatkan WindowInfoTracker untuk memproses perubahan tata letak apa pun.

step1/FoldingStateActor.kt

windowInfoTracker.windowLayoutInfo(activity)
      .collect { newLayoutInfo ->
         activeWindowLayoutInfo = newLayoutInfo
         updateLayoutByFoldingState(cameraViewfinder)
      }

Dengan menggunakan antarmuka WindowInfoTracker, Anda dapat memanggil windowLayoutInfo() untuk mengumpulkan Flow dari WindowLayoutInfo yang berisi semua informasi yang tersedia di DisplayFeature.

Langkah terakhir adalah bereaksi terhadap perubahan ini dan memindahkan konten yang sesuai. Anda melakukan ini di dalam metode updateLayoutByFoldingState(), selangkah demi selangkah.

  1. Pastikan activityLayoutInfo berisi beberapa properti DisplayFeature, dan setidaknya salah satunya adalah FoldingFeature. Jika tidak, Anda tidak perlu melakukan apa pun:

step1/FoldingStateActor.kt

val foldingFeature = activeWindowLayoutInfo?.displayFeatures
            ?.firstOrNull { it is FoldingFeature } as FoldingFeature?
            ?: return
  1. Hitung posisi lipatan untuk memastikan posisi perangkat memengaruhi tata letak Anda dan tidak berada di luar batas hierarki Anda:

step1/FoldingStateActor.kt

val foldPosition = FoldableUtils.getFeaturePositionInViewRect(
            foldingFeature,
            cameraViewfinder.parent as View
        ) ?: return

Sekarang, Anda yakin telah memiliki FoldingFeature yang memengaruhi tata letak, jadi Anda perlu memindahkan konten Anda.

  1. Periksa apakah FoldingFeature menampilkan HALF_OPEN atau cukup pulihkan posisi konten Anda. Jika yang ditampilkan adalah HALF_OPEN, Anda perlu menjalankan pemeriksaan lain dan bertindak berbeda berdasarkan orientasi lipatan:

step1/FoldingStateActor.kt

if (foldingFeature.state == FoldingFeature.State.HALF_OPENED) {
    when (foldingFeature.orientation) {
        FoldingFeature.Orientation.VERTICAL -> {
            cameraViewfinder.moveToRightOf(foldPosition)
        }
        FoldingFeature.Orientation.HORIZONTAL -> {
            cameraViewfinder.moveToTopOf(foldPosition)
        }
    }
} else {
    cameraViewfinder.restore()
}

Jika lipatannya VERTICAL, Anda memindahkan konten ke kanan. Jika tidak, Anda memindahkannya ke atas posisi lipatan.

  1. Bangun dan jalankan aplikasi Anda, lalu bentangkan perangkat Anda dan tempatkan dalam mode di atas meja untuk melihat konten bergerak sebagaimana yang dimaksudkan.

7. Selamat

Dalam codelab ini, Anda telah mempelajari keistimewaan perangkat foldable, perubahan postur, dan Rear Display API.

Bacaan lebih lanjut

Referensi