Praktik yang direkomendasikan

Aplikasi untuk perangkat foldable dan multi-layar

Secara umum, aplikasi tidak boleh mengandalkan ID statis atau logika yang bergantung pada beberapa ID tampilan. Dalam sebagian besar kasus, aplikasi harus mengubah ukuran dan berfungsi di berbagai layar dan sistem harus mengontrol lokasi aplikasi. Misalnya, untuk membuat pengalaman baru dan unik bagi perangkat foldable serta meluncurkan aplikasi khusus di layar eksternal saat perangkat dilipat.

Dalam hal ini, SystemUI (atau komponen sistem lain) harus mendeteksi lipatan, menentukan apakah tindakan perlu dilakukan, lalu meluncurkan aktivitas target dan menentukan ID tampilan eksternal sebagai target peluncuran. Aplikasi tidak boleh mendeteksi tindakan ini atau melakukan tindakan apa pun sebagai respons, lalu meluncurkan di layar tertentu. Dengan kata lain, jangan menganggap bahwa apa yang berfungsi di satu perangkat akan berfungsi di perangkat lain. Singkatnya, kode khusus perangkat meningkatkan fragmentasi.

Membatasi akses ke layar

Jika konfigurasi perangkat memerlukan pembatasan akses ke satu atau beberapa layar, sebaiknya gunakan flag Display#FLAG_PRIVATE untuk menetapkan layar tersebut sebagai pribadi. Tindakan ini akan membatasi semua orang kecuali pemilik untuk menambahkan konten ke layar. Setiap upaya untuk meluncurkan aktivitas atau menambahkan jendela oleh siapa pun selain pemilik akan menghasilkan SecurityException. Jika sistem memiliki tampilan, sistem dapat menambahkan jendela dan meluncurkan aktivitas.

Selain itu, entitas yang ditempatkan di layar selalu dapat mengakses layar tersebut. Jika pemilik meluncurkan aktivitas di layar, maka aktivitas tersebut dapat meluncurkan aktivitas lain di layar ini. Oleh karena itu, pemilik bertanggung jawab untuk membatasi akses dan mengizinkan aplikasi tepercaya saja.

Selain itu, lebih banyak batasan ditambahkan ke layar virtual karena aplikasi apa pun dapat membuat layar virtual tanpa membuatnya terlihat oleh pengguna. Jika tampilan virtual tidak dimiliki oleh sistem, hanya aktivitas dengan allowEmbedded yang diizinkan dan pemanggil harus memiliki izin ACTIVITY_EMBEDDING.

Untuk informasi selengkapnya, lihat:

  • ActivityStackSupervisor#isCallerAllowedToLaunchOnDisplay()
  • ActivityDisplay#isUidPresent()
  • DisplayManagerService#isUidPresentOnDisplay()

Untuk mengontrol peluncuran aktivitas secara bersyarat, gunakan LaunchParamsController, yang mencegat semua peluncuran aktivitas dan memungkinkan komponen sistem mengubah parameter yang digunakan untuk peluncuran. Fitur ini tersedia di system_server.

Mengonfigurasi setelan windowing tampilan dan dekorasi sistem

Dekorasi sistem dapat dikonfigurasi per tampilan di DisplayWindowSettings. Implementasi perangkat dapat memberikan konfigurasi default di /data/system/display_settings.xml.

Nilai ini menentukan apakah dekorasi sistem (peluncur, wallpaper, panel navigasi, dan jendela dekorasi lainnya) serta IME muncul di layar. Untuk mengetahui detailnya, lihat DisplayWindowSettings#shouldShowSystemDecorsLocked() dan DisplayWindowSettings#shouldShowImeLocked().

Untuk mengidentifikasi layar, gunakan ID unik (default ini menggunakan DisplayInfo#uniqueId) atau ID port fisik untuk layar hardware (lihat DisplayInfo#address).

Misalnya, contoh konfigurasi tampilan berikut mengaktifkan dekorasi sistem dan IME pada tampilan simulasi:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<display-settings>
<config identifier="0" />
<display
  name="overlay:1"
  shouldShowSystemDecors="true"
  shouldShowIme="true" />
</display-settings>

Pada contoh di atas, uniqueId digunakan untuk identifikasi tampilan dalam atribut nama, yang untuk tampilan simulasi adalah overlay:1. Untuk tampilan bawaan, nilai sampel dapat berupa "local:45354385242535243453". Opsi lainnya adalah menggunakan informasi port hardware dan menetapkan identifier="1" agar sesuai dengan DisplayWindowSettings#IDENTIFIER_PORT, lalu memperbarui nama untuk menggunakan format "port:<port_id>":

<?xmlversion='1.0' encoding='utf-8' standalone='yes' ?>
<display-settings>
<config identifier="1" />
<display
  name="port:12345"
  shouldShowSystemDecors="true"
  shouldShowIme="true" />
</display-settings>

Untuk mengetahui detailnya, lihat ID tampilan statis.

Untuk informasi selengkapnya, lihat:

Beralih tampilan antara tugas pencerminan dan hosting

Di Android 17 dan yang lebih tinggi, DisplayManager menggunakan flag FLAG_ALLOWS_CONTENT_MODE_SWITCH untuk mengontrol apakah layar beralih antara pencerminan dan hosting tugas saat runtime. Secara default, tanda ini diaktifkan untuk layar eksternal dan dinonaktifkan untuk semua layar lainnya.

Jika FLAG_ALLOWS_CONTENT_MODE_SWITCH ada, DisplayManager memantau setelan aman android.provider.Settings.Secure.MIRROR_BUILT_IN_DISPLAY untuk menentukan apakah akan mencerminkan atau menghosting tugas. Meskipun ini adalah logika default, OEM dapat menyesuaikan perilaku ini.

Menampilkan topologi dan gerakan pointer

Di Android 17 dan yang lebih tinggi, topologi layar menentukan posisi relatif layar dan membatasi pergerakan kursor mouse ke kumpulan layar tertentu dalam topologi.

WindowManager memutuskan untuk menyertakan layar dalam topologi dan memanggil DisplayManagerInternal.onDisplayBelongToTopologyChanged. DisplayManager memeriksa DisplayTopologyCoordinator.isDisplayAllowedInTopology sebelum menambahkan tampilan. Secara default, jika layar lokal dapat menghosting tugas, sistem akan menambahkannya.

Jika ada beberapa tampilan publik yang dapat menghosting tugas, keputusan untuk menyertakan tampilan default ditangani oleh penyedia boolean shouldIncludeDefaultDisplayInTopology yang diteruskan ke DisplayTopologyCoordinator. Jika tampilan default adalah satu-satunya tampilan publik yang dapat menghosting tugas, tampilan tersebut selalu ada dalam topologi. Di AOSP, penyedia boolean menampilkan true hanya jika layar default mendukung mode jendela desktop atau jika setelan aman Settings.Secure.INCLUDE_DEFAULT_DISPLAY_IN_TOPOLOGY adalah true.

Aplikasi mengkueri topologi saat ini menggunakan DisplayManager.getDisplayTopology dan bereaksi terhadap perubahan topologi dengan mendaftarkan pemroses dengan DisplayManager.registerTopologyListener.