Perubahan perilaku: Aplikasi yang menargetkan Android 15 atau yang lebih tinggi

Seperti rilis sebelumnya, Android 15 menyertakan perubahan perilaku yang mungkin memengaruhi aplikasi Anda. Perubahan perilaku berikut ini berlaku khusus bagi aplikasi yang menargetkan Android 15 atau yang lebih tinggi. Jika aplikasi Anda menargetkan Android 15 atau yang lebih tinggi, Anda harus memodifikasi aplikasi untuk mendukung perilaku ini dengan benar, jika berlaku.

Pastikan Anda juga meninjau daftar perubahan perilaku yang memengaruhi semua aplikasi yang berjalan di Android 15, terlepas dari targetSdkVersion aplikasi Anda.

Fungsi inti

Android 15 mengubah atau memperluas berbagai kemampuan inti sistem Android.

Perubahan pada layanan latar depan

We are making the following changes to foreground services with Android 15.

Data sync foreground service timeout behavior

Android 15 memperkenalkan perilaku waktu tunggu baru ke dataSync untuk aplikasi yang menargetkan Android 15 (API level 35) atau yang lebih tinggi. Perilaku ini juga berlaku untuk jenis layanan latar depan mediaProcessing baru.

Sistem mengizinkan layanan dataSync aplikasi berjalan selama total 6 jam dalam periode 24 jam, setelah itu sistem akan memanggil metode Service.onTimeout(int, int) layanan yang berjalan (diperkenalkan di Android 15). Saat ini, layanan memiliki waktu beberapa detik untuk memanggil Service.stopSelf(). Saat Service.onTimeout() dipanggil, layanan tidak lagi dianggap sebagai layanan latar depan. Jika layanan tidak memanggil Service.stopSelf(), sistem akan menampilkan pengecualian internal. Pengecualian akan dicatat ke dalam log di Logcat dengan pesan berikut:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"

Untuk menghindari masalah terkait perubahan perilaku ini, Anda dapat melakukan satu atau beberapa hal berikut:

  1. Minta layanan Anda menerapkan metode Service.onTimeout(int, int) baru. Saat aplikasi Anda menerima callback, pastikan untuk memanggil stopSelf() dalam beberapa detik. (Jika Anda tidak segera menghentikan aplikasi, sistem akan menghasilkan kegagalan.)
  2. Pastikan layanan dataSync aplikasi Anda tidak berjalan selama lebih dari 6 jam dalam periode 24 jam (kecuali jika pengguna berinteraksi dengan aplikasi, mereset timer).
  3. Hanya mulai layanan latar depan dataSync sebagai hasil dari interaksi pengguna langsung; karena aplikasi Anda berada di latar depan saat layanan dimulai, layanan Anda memiliki waktu enam jam penuh setelah aplikasi beralih ke latar belakang.
  4. Sebagai ganti menggunakan layanan latar depan dataSync, gunakan API alternatif.

Jika layanan latar depan dataSync aplikasi Anda telah berjalan selama 6 jam dalam 24 jam terakhir, Anda tidak dapat memulai layanan latar depan dataSync lain kecuali pengguna telah memindahkan aplikasi Anda ke latar depan (yang mereset timer). Jika Anda mencoba memulai layanan latar depan dataSync lainnya, sistem akan menampilkan ForegroundServiceStartNotAllowedException dengan pesan error seperti "Batas waktu sudah habis untuk jenis layanan latar depan dataSync".

Pengujian

Untuk menguji perilaku aplikasi, Anda dapat mengaktifkan waktu tunggu sinkronisasi data meskipun aplikasi tidak menargetkan Android 15 (asalkan aplikasi berjalan di perangkat Android 15). Untuk mengaktifkan waktu tunggu, jalankan perintah adb berikut:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

Anda juga dapat menyesuaikan periode waktu tunggu untuk mempermudah pengujian perilaku aplikasi saat batas tercapai. Untuk menetapkan periode waktu tunggu baru, jalankan perintah adb berikut:

adb shell device_config put activity_manager data_sync_fgs_timeout_duration duration-in-milliseconds

New media processing foreground service type

Android 15 memperkenalkan jenis layanan latar depan baru, mediaProcessing. Jenis layanan ini sesuai untuk operasi seperti melakukan transcoding file media. Misalnya, aplikasi media mungkin mendownload file audio dan perlu mengonversinya ke format lain sebelum memutarnya. Anda dapat menggunakan layanan latar depan mediaProcessing untuk memastikan konversi berlanjut bahkan saat aplikasi berada di latar belakang.

Sistem mengizinkan layanan mediaProcessing aplikasi berjalan selama total 6 jam dalam periode 24 jam, setelah itu sistem akan memanggil metode Service.onTimeout(int, int) layanan yang berjalan (diperkenalkan di Android 15). Saat ini, layanan memiliki waktu beberapa detik untuk memanggil Service.stopSelf(). Jika layanan tidak memanggil Service.stopSelf(), sistem akan menampilkan pengecualian internal. Pengecualian akan dicatat ke dalam log di Logcat dengan pesan berikut:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"

Untuk menghindari pengecualian, Anda dapat melakukan salah satu hal berikut:

  1. Minta layanan Anda menerapkan metode Service.onTimeout(int, int) baru. Saat aplikasi Anda menerima callback, pastikan untuk memanggil stopSelf() dalam beberapa detik. (Jika Anda tidak segera menghentikan aplikasi, sistem akan menghasilkan kegagalan.)
  2. Pastikan layanan mediaProcessing aplikasi Anda tidak berjalan selama lebih dari jumlah 6 jam dalam periode 24 jam (kecuali jika pengguna berinteraksi dengan aplikasi, mereset timer).
  3. Hanya mulai layanan latar depan mediaProcessing sebagai hasil dari interaksi pengguna langsung; karena aplikasi Anda berada di latar depan saat layanan dimulai, layanan Anda memiliki waktu enam jam penuh setelah aplikasi beralih ke latar belakang.
  4. Daripada menggunakan layanan latar depan mediaProcessing, gunakan API alternatif, seperti WorkManager.

Jika layanan latar depan mediaProcessing aplikasi Anda telah berjalan selama 6 jam dalam 24 terakhir, Anda tidak dapat memulai layanan latar depan mediaProcessing lainnya kecuali jika pengguna telah memindahkan aplikasi Anda ke latar depan (yang akan mereset timer). Jika Anda mencoba memulai layanan latar depan mediaProcessing lainnya, sistem akan menampilkan ForegroundServiceStartNotAllowedException dengan pesan error seperti "Batas waktu sudah habis untuk jenis layanan latar depan mediaProcessing".

Untuk informasi selengkapnya tentang jenis layanan mediaProcessing, lihat Perubahan pada jenis layanan latar depan untuk Android 15: Pemrosesan media.

Pengujian

Untuk menguji perilaku aplikasi, Anda dapat mengaktifkan waktu tunggu pemrosesan media meskipun aplikasi tidak menargetkan Android 15 (selama aplikasi berjalan di perangkat Android 15). Untuk mengaktifkan waktu tunggu, jalankan perintah adb berikut:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

Anda juga dapat menyesuaikan periode waktu tunggu untuk mempermudah pengujian perilaku aplikasi saat batas tercapai. Untuk menetapkan periode waktu tunggu baru, jalankan perintah adb berikut:

adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds

Restrictions on BOOT_COMPLETED broadcast receivers launching foreground services

There are new restrictions on BOOT_COMPLETED broadcast receivers launching foreground services. BOOT_COMPLETED receivers are not allowed to launch the following types of foreground services:

If a BOOT_COMPLETED receiver tries to launch any of those types of foreground services, the system throws ForegroundServiceStartNotAllowedException.

Testing

To test your app's behavior, you can enable these new restrictions even if your app is not targeting Android 15 (as long as the app is running on an Android 15 device). Run the following adb command:

adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name

To send a BOOT_COMPLETED broadcast without restarting the device, run the following adb command:

adb shell am broadcast -a android.intent.action.BOOT_COMPLETED your-package-name

Restrictions on starting foreground services while an app holds the SYSTEM_ALERT_WINDOW permission

Sebelumnya, jika memiliki izin SYSTEM_ALERT_WINDOW, aplikasi dapat meluncurkan layanan latar depan meskipun aplikasi saat ini berada di latar belakang (seperti yang dibahas dalam pengecualian dari pembatasan mulai latar belakang).

Jika aplikasi menargetkan Android 15, pengecualian ini kini lebih sempit. Aplikasi kini harus memiliki izin SYSTEM_ALERT_WINDOW dan juga memiliki jendela overlay yang terlihat. Artinya, aplikasi harus meluncurkan jendela TYPE_APPLICATION_OVERLAY terlebih dahulu dan jendela harus terlihat sebelum Anda memulai layanan latar depan.

Jika aplikasi Anda mencoba memulai layanan latar depan dari latar belakang tanpa memenuhi persyaratan baru ini (dan tidak memiliki pengecualian lain), sistem akan menampilkan ForegroundServiceStartNotAllowedException.

Jika aplikasi Anda mendeklarasikan izin SYSTEM_ALERT_WINDOW dan meluncurkan layanan latar depan dari latar belakang, aplikasi tersebut mungkin akan terpengaruh oleh perubahan ini. Jika aplikasi Anda mendapatkan ForegroundServiceStartNotAllowedException, periksa urutan operasi aplikasi dan pastikan aplikasi Anda sudah memiliki jendela overlay yang aktif sebelum mencoba memulai layanan latar depan dari latar belakang. Anda dapat memeriksa apakah jendela overlay saat ini terlihat dengan memanggil View.getWindowVisibility(), atau Anda dapat mengganti View.onWindowVisibilityChanged() untuk mendapatkan notifikasi setiap kali visibilitas berubah.

Pengujian

Untuk menguji perilaku aplikasi, Anda dapat mengaktifkan pembatasan baru ini meskipun aplikasi tidak menargetkan Android 15 (selama aplikasi berjalan di perangkat Android 15). Untuk mengaktifkan pembatasan baru ini saat memulai layanan latar depan dari latar belakang, jalankan perintah adb berikut:

adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name

Perubahan pada waktu aplikasi dapat mengubah status global mode Jangan Ganggu

Apps that target Android 15 (API level 35) and higher can no longer change the global state or policy of Do Not Disturb (DND) on a device (either by modifying user settings, or turning off DND mode). Instead, apps must contribute an AutomaticZenRule, which the system combines into a global policy with the existing most-restrictive-policy-wins scheme. Calls to existing APIs that previously affected global state (setInterruptionFilter, setNotificationPolicy) result in the creation or update of an implicit AutomaticZenRule, which is toggled on and off depending on the call-cycle of those API calls.

Note that this change only affects observable behavior if the app is calling setInterruptionFilter(INTERRUPTION_FILTER_ALL) and expects that call to deactivate an AutomaticZenRule that was previously activated by their owners.

Perubahan API OpenJDK

Android 15 melanjutkan pekerjaan memuat ulang library inti Android agar selaras dengan fitur dalam rilis OpenJDK LTS terbaru.

Beberapa perubahan ini dapat memengaruhi kompatibilitas aplikasi yang menargetkan Android 15 (level API 35):

  • Perubahan pada API pemformatan string: Validasi indeks argumen, flag, lebar, dan presisi kini lebih ketat saat menggunakan API String.format() dan Formatter.format() berikut:

    Misalnya, pengecualian berikut terjadi saat indeks argumen 0 digunakan (%0 dalam string format):

    IllegalFormatArgumentIndexException: Illegal format argument index = 0
    

    Dalam hal ini, masalah dapat diperbaiki dengan menggunakan indeks argumen 1 (%1 dalam string format).

  • Perubahan pada jenis komponen Arrays.asList(...).toArray(): Saat menggunakan Arrays.asList(...).toArray(), jenis komponen array yang dihasilkan sekarang adalah Object—bukan jenis elemen array yang mendasarinya. Jadi, kode berikut akan memunculkan ClassCastException:

    String[] elements = (String[]) Arrays.asList("one", "two").toArray();
    

    Untuk kasus ini, guna mempertahankan String sebagai jenis komponen dalam array yang dihasilkan, Anda dapat menggunakan Collection.toArray(Object[]):

    String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
    
  • Perubahan pada penanganan kode bahasa: Saat menggunakan Locale API, kode bahasa untuk Ibrani, Yiddish, dan Indonesia tidak lagi dikonversi ke bentuknya yang sudah tidak digunakan (Ibrani: iw, Yiddish: ji, dan Indonesia: in). Saat menentukan kode bahasa untuk salah satu lokalitas ini, gunakan kode dari ISO 639-1 (Ibrani: he, Yiddish: yi, dan Indonesia: id).

  • Perubahan pada urutan bilangan bulat acak: Setelah perubahan yang dilakukan di https://bugs.openjdk.org/browse/JDK-8301574, metode Random.ints() berikut kini menampilkan urutan angka yang berbeda dengan metode Random.nextInt():

    Umumnya, perubahan ini tidak akan menyebabkan perilaku yang merusak aplikasi, tetapi kode Anda tidak boleh mengharapkan urutan yang dihasilkan dari metode Random.ints() agar cocok dengan Random.nextInt().

API SequencedCollection baru dapat memengaruhi kompatibilitas aplikasi Anda setelah Anda mengupdate compileSdk dalam konfigurasi build aplikasi untuk menggunakan Android 15 (level API 35):

  • Konflik dengan fungsi ekstensi MutableList.removeFirst() dan MutableList.removeLast() di kotlin-stdlib

    Jenis List di Java dipetakan ke jenis MutableList di Kotlin. Karena API List.removeFirst() dan List.removeLast() telah diperkenalkan di Android 15 (level API 35), compiler Kotlin menyelesaikan panggilan fungsi, misalnya list.removeFirst(), secara statis ke API List baru, bukan ke fungsi ekstensi di kotlin-stdlib.

    Jika aplikasi dikompilasi ulang dengan compileSdk ditetapkan ke 35 dan minSdk ditetapkan ke 34 atau yang lebih rendah, lalu aplikasi dijalankan di Android 14 dan yang lebih rendah, error runtime akan terjadi:

    java.lang.NoSuchMethodError: No virtual method
    removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
    

    Opsi lint NewApi yang ada di Plugin Android Gradle dapat menangkap penggunaan API baru ini.

    ./gradlew lint
    
    MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi]
          list.removeFirst()
    

    Untuk memperbaiki pengecualian runtime dan error lint, panggilan fungsi removeFirst() dan removeLast() dapat diganti dengan removeAt(0) dan removeAt(list.lastIndex) masing-masing di Kotlin. Jika Anda menggunakan Android Studio Ladybug | 2024.1.3 atau yang lebih tinggi, opsi perbaikan cepat untuk error ini juga tersedia.

    Pertimbangkan untuk menghapus @SuppressLint("NewApi") dan lintOptions { disable 'NewApi' } jika opsi lint telah dinonaktifkan.

  • Konflik dengan metode lain di Java

    Metode baru telah ditambahkan ke jenis yang ada, misalnya, List dan Deque. Metode baru ini mungkin tidak kompatibel dengan metode yang memiliki nama dan jenis argumen yang sama di antarmuka dan class lainnya. Jika terjadi tabrakan tanda tangan metode dengan ketidakcocokan, compiler javac akan menghasilkan error waktu build. Contoh:

    Contoh error 1:

    javac MyList.java
    
    MyList.java:135: error: removeLast() in MyList cannot implement removeLast() in List
      public void removeLast() {
                  ^
      return type void is not compatible with Object
      where E is a type-variable:
        E extends Object declared in interface List
    

    Contoh error 2:

    javac MyList.java
    
    MyList.java:7: error: types Deque<Object> and List<Object> are incompatible;
    public class MyList implements  List<Object>, Deque<Object> {
      both define reversed(), but with unrelated return types
    1 error
    

    Contoh error 3:

    javac MyList.java
    
    MyList.java:43: error: types List<E#1> and MyInterface<E#2> are incompatible;
    public static class MyList implements List<Object>, MyInterface<Object> {
      class MyList inherits unrelated defaults for getFirst() from types List and MyInterface
      where E#1,E#2 are type-variables:
        E#1 extends Object declared in interface List
        E#2 extends Object declared in interface MyInterface
    1 error
    

    Untuk memperbaiki error build ini, class yang mengimplementasikan antarmuka ini harus mengganti metode dengan jenis nilai yang ditampilkan yang kompatibel. Contoh:

    @Override
    public Object getFirst() {
        return List.super.getFirst();
    }
    

Keamanan

Android 15 menyertakan perubahan yang meningkatkan keamanan sistem untuk membantu melindungi aplikasi dan pengguna dari aplikasi berbahaya.

Versi TLS yang dibatasi

Android 15 membatasi penggunaan TLS versi 1.0 dan 1.1. Versi ini sebelumnya tidak digunakan lagi di Android, tetapi sekarang tidak diizinkan untuk aplikasi yang menargetkan Android 15.

Peluncuran aktivitas latar belakang yang diamankan

Android 15 protects users from malicious apps and gives them more control over their devices by adding changes that prevent malicious background apps from bringing other apps to the foreground, elevating their privileges, and abusing user interaction. Background activity launches have been restricted since Android 10 (API level 29).

Other changes

In addition to the restriction for UID matching, these other changes are also included:

  • Change PendingIntent creators to block background activity launches by default. This helps prevent apps from accidentally creating a PendingIntent that could be abused by malicious actors.
  • Don't bring an app to the foreground unless the PendingIntent sender allows it. This change aims to prevent malicious apps from abusing the ability to start activities in the background. By default, apps are not allowed to bring the task stack to the foreground unless the creator allows background activity launch privileges or the sender has background activity launch privileges.
  • Control how the top activity of a task stack can finish its task. If the top activity finishes a task, Android will go back to whichever task was last active. Moreover, if a non-top activity finishes its task, Android will go back to the home screen; it won't block the finish of this non-top activity.
  • Prevent launching arbitrary activities from other apps into your own task. This change prevents malicious apps from phishing users by creating activities that appear to be from other apps.
  • Block non-visible windows from being considered for background activity launches. This helps prevent malicious apps from abusing background activity launches to display unwanted or malicious content to users.

Intent yang lebih aman

Android 15 memperkenalkan langkah keamanan opsional baru untuk membuat intent lebih aman dan lebih tangguh. Perubahan ini bertujuan untuk mencegah potensi kerentanan dan penyalahgunaan intent yang dapat dieksploitasi oleh aplikasi berbahaya. Ada dua peningkatan utama pada keamanan intent di Android 15:

  • Mencocokkan filter intent target: Intent yang menargetkan komponen tertentu harus sesuai dengan spesifikasi filter intent target secara akurat. Jika Anda mengirim intent untuk meluncurkan aktivitas aplikasi lain, komponen intent target harus selaras dengan filter intent yang dideklarasikan aktivitas penerima.
  • Intent harus memiliki tindakan: Intent tanpa tindakan tidak akan cocok lagi filter intent apa pun. Ini berarti intent yang digunakan untuk memulai aktivitas atau layanan harus memiliki tindakan yang didefinisikan dengan jelas.

Untuk memeriksa bagaimana aplikasi Anda merespons perubahan ini, gunakan StrictMode di aplikasi Anda. Untuk melihat detail log tentang pelanggaran penggunaan Intent, tambahkan metode berikut:

Kotlin

fun onCreate() {
    StrictMode.setVmPolicy(VmPolicy.Builder()
        .detectUnsafeIntentLaunch()
        .build()
    )
}

Java

public void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
            .detectUnsafeIntentLaunch()
            .build());
}

Pengalaman pengguna dan UI sistem

Android 15 menyertakan beberapa perubahan yang dimaksudkan untuk menciptakan pengalaman pengguna yang lebih konsisten dan intuitif.

Perubahan inset jendela

There are two changes related to window insets in Android 15: edge-to-edge is enforced by default, and there are also configuration changes, such as the default configuration of system bars.

Penerapan menyeluruh

Aplikasi ditampilkan dalam layar penuh secara default di perangkat yang menjalankan Android 15 jika aplikasi menargetkan Android 15 (level API 35).

Aplikasi yang menargetkan Android 14 dan tidak ditampilkan layar penuh di perangkat Android 15.


Aplikasi yang menargetkan Android 15 (level API 35) dan ditampilkan di layar penuh pada perangkat Android 15. Aplikasi ini sebagian besar menggunakan Komponen Compose Material 3 yang otomatis menerapkan inset. Layar ini tidak terpengaruh secara negatif oleh penerapan layar penuh Android 15.

Ini adalah perubahan yang dapat menyebabkan gangguan dan berdampak negatif pada UI aplikasi Anda. Perubahan memengaruhi area UI berikut:

  • Menu navigasi dengan tuas gestur
    • Transparan secara default.
    • Offset bawah dinonaktifkan sehingga konten digambar di belakang kolom navigasi sistem, kecuali jika inset diterapkan.
    • setNavigationBarColor dan R.attr#navigationBarColor tidak digunakan lagi dan tidak memengaruhi navigasi gestur.
    • setNavigationBarContrastEnforced dan R.attr#navigationBarContrastEnforced tetap tidak berpengaruh pada navigasi gestur.
  • Navigasi 3 tombol
    • Opasitas ditetapkan ke 80% secara default, dengan warna yang mungkin cocok dengan latar belakang jendela.
    • Offset bawah dinonaktifkan sehingga konten digambar di belakang menu navigasi sistem kecuali jika inset diterapkan.
    • setNavigationBarColor dan R.attr#navigationBarColor ditetapkan agar sesuai dengan latar belakang jendela secara default. Latar belakang jendela harus berupa drawable warna agar default ini diterapkan. API ini sudah tidak digunakan lagi, tetapi terus memengaruhi navigasi 3 tombol.
    • setNavigationBarContrastEnforced dan R.attr#navigationBarContrastEnforced bernilai benar secara default, yang menambahkan latar belakang buram 80% di seluruh navigasi 3 tombol.
  • Status bar
    • Transparan secara default.
    • Offset atas dinonaktifkan sehingga konten digambar di belakang status bar kecuali jika inset diterapkan.
    • setStatusBarColor dan R.attr#statusBarColor tidak digunakan lagi dan tidak berpengaruh pada Android 15.
    • setStatusBarContrastEnforced dan R.attr#statusBarContrastEnforced tidak digunakan lagi, tetapi masih memiliki efek pada Android 15.
  • Potongan layar
    • layoutInDisplayCutoutMode jendela non-floating harus berupa LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS. SHORT_EDGES, NEVER, dan DEFAULT ditafsirkan sebagai ALWAYS sehingga pengguna tidak melihat batang hitam yang disebabkan oleh potongan layar dan muncul di layar penuh.

Contoh berikut menunjukkan aplikasi sebelum dan sesudah menargetkan Android 15 (level API 35), serta sebelum dan sesudah menerapkan inset.

Aplikasi yang menargetkan Android 14 dan tidak ditampilkan layar penuh di perangkat Android 15.
Aplikasi yang menargetkan Android 15 (level API 35) dan ditampilkan di layar penuh pada perangkat Android 15. Namun, banyak elemen kini disembunyikan oleh kolom status, kolom navigasi 3 tombol, atau potongan layar karena penerapan layar penuh Android 15. UI tersembunyi mencakup panel aplikasi atas Material 2, tombol tindakan mengambang, dan item daftar.
Aplikasi yang menargetkan Android 15 (level API 35), ditampilkan dalam layar penuh di perangkat Android 15 dan menerapkan inset sehingga UI tidak tersembunyi.
Yang perlu diperiksa jika aplikasi Anda sudah ditampilkan di layar penuh

Jika aplikasi Anda sudah ditampilkan layar penuh dan menerapkan inset, Anda sebagian besar tidak terpengaruh, kecuali dalam skenario berikut. Namun, meskipun Anda merasa tidak terpengaruh, sebaiknya Anda menguji aplikasi Anda.

  • Anda memiliki jendela non-mengambang, seperti Activity yang menggunakan SHORT_EDGES, NEVER, atau DEFAULT, bukan LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS. Jika aplikasi Anda error saat diluncurkan, penyebabnya mungkin adalah layar pembuka. Anda dapat mengupgrade dependensi layar pembuka inti ke 1.2.0-alpha01 atau yang lebih baru atau menetapkan window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always.
  • Mungkin ada layar dengan traffic lebih rendah dengan UI yang tertutup. Pastikan layar yang jarang dikunjungi ini tidak memiliki UI yang tertutup. Layar dengan traffic lebih rendah mencakup:
    • Layar aktivasi atau login
    • Halaman setelan
Yang harus diperiksa jika aplikasi Anda belum ditampilkan di layar penuh

Jika aplikasi Anda belum ditampilkan dalam layar penuh, kemungkinan besar Anda akan terpengaruh. Selain skenario untuk aplikasi yang sudah ditampilkan di layar penuh, Anda harus mempertimbangkan hal berikut:

  • Jika aplikasi Anda menggunakan Komponen Material 3 ( androidx.compose.material3) di Compose, seperti TopAppBar, BottomAppBar, dan NavigationBar, komponen ini kemungkinan tidak terpengaruh karena otomatis menangani inset.
  • Jika aplikasi Anda menggunakan Komponen Material 2 ( androidx.compose.material) di Compose, komponen ini tidak otomatis menangani inset. Namun, Anda dapat memperoleh akses ke inset dan menerapkannya secara manual. Di androidx.compose.material 1.6.0 dan yang lebih baru, gunakan parameter windowInsets untuk menerapkan inset secara manual bagi BottomAppBar, TopAppBar, BottomNavigation, dan NavigationRail. Demikian pula, gunakan parameter contentWindowInsets untuk Scaffold.
  • Jika aplikasi Anda menggunakan tampilan dan Komponen Material (com.google.android.material), sebagian besar Komponen Material berbasis tampilan seperti BottomNavigationView, BottomAppBar, NavigationRailView, atau NavigationView, menangani inset dan tidak memerlukan pekerjaan tambahan. Namun, Anda perlu menambahkan android:fitsSystemWindows="true" jika menggunakan AppBarLayout.
  • Untuk composable kustom, terapkan inset secara manual sebagai padding. Jika konten Anda berada dalam Scaffold, Anda dapat menggunakan inset dengan nilai padding Scaffold. Jika tidak, terapkan padding menggunakan salah satu WindowInsets.
  • Jika aplikasi Anda menggunakan tampilan dan BottomSheet, SideSheet, atau kontainer kustom, terapkan padding menggunakan ViewCompat.setOnApplyWindowInsetsListener. Untuk RecyclerView, terapkan padding menggunakan pemroses ini dan juga tambahkan clipToPadding="false".
Yang harus diperiksa jika aplikasi Anda harus menawarkan perlindungan latar belakang kustom

Jika aplikasi Anda harus menawarkan perlindungan latar belakang kustom untuk navigasi 3 tombol atau status bar, aplikasi Anda harus menempatkan composable atau tampilan di belakang kolom sistem menggunakan WindowInsets.Type#tappableElement() untuk mendapatkan tinggi kolom navigasi 3 tombol atau WindowInsets.Type#statusBars.

Referensi layar penuh tambahan

Lihat panduan Tampilan Layar Penuh dan Compose Layar Penuh untuk pertimbangan tambahan tentang penerapan inset.

API yang tidak digunakan lagi

API berikut tidak digunakan lagi, tetapi tidak dinonaktifkan:

API berikut tidak digunakan lagi dan dinonaktifkan:

Konfigurasi stabil

Jika aplikasi Anda menargetkan Android 15 (level API 35) atau yang lebih tinggi, Configuration tidak lagi mengecualikan kolom sistem. Jika Anda menggunakan ukuran layar di class Configuration untuk penghitungan tata letak, Anda harus menggantinya dengan alternatif yang lebih baik seperti ViewGroup, WindowInsets, atau WindowMetricsCalculator yang sesuai, bergantung pada kebutuhan Anda.

Configuration telah tersedia sejak API 1. Biasanya diperoleh dari Activity.onConfigurationChanged. Laporan ini memberikan informasi seperti kepadatan jendela, orientasi, dan ukuran. Salah satu karakteristik penting tentang ukuran jendela yang ditampilkan dari Configuration adalah bahwa sebelumnya ukuran tersebut tidak menyertakan kolom sistem.

Ukuran konfigurasi biasanya digunakan untuk pemilihan resource, seperti /res/layout-h500dp, dan ini masih merupakan kasus penggunaan yang valid. Namun, penggunaannya untuk penghitungan tata letak selalu tidak disarankan. Jika Anda melakukannya, Anda harus menjauh dari perangkat tersebut sekarang. Anda harus mengganti penggunaan Configuration dengan sesuatu yang lebih sesuai, bergantung pada kasus penggunaan Anda.

Jika Anda menggunakannya untuk menghitung tata letak, gunakan ViewGroup yang sesuai, seperti CoordinatorLayout atau ConstraintLayout. Jika Anda menggunakannya untuk menentukan tinggi navbar sistem, gunakan WindowInsets. Jika Anda ingin mengetahui ukuran jendela aplikasi saat ini, gunakan computeCurrentWindowMetrics.

Daftar berikut menjelaskan kolom yang terpengaruh oleh perubahan ini:

Atribut elegantTextHeight secara default adalah benar (true)

For apps targeting Android 15 (API level 35), the elegantTextHeight TextView attribute becomes true by default, replacing the compact font used by default with some scripts that have large vertical metrics with one that is much more readable. The compact font was introduced to prevent breaking layouts; Android 13 (API level 33) prevents many of these breakages by allowing the text layout to stretch the vertical height utilizing the fallbackLineSpacing attribute.

In Android 15, the compact font still remains in the system, so your app can set elegantTextHeight to false to get the same behavior as before, but it is unlikely to be supported in upcoming releases. So, if your app supports the following scripts: Arabic, Lao, Myanmar, Tamil, Gujarati, Kannada, Malayalam, Odia, Telugu or Thai, test your app by setting elegantTextHeight to true.

elegantTextHeight behavior for apps targeting Android 14 (API level 34) and lower.
elegantTextHeight behavior for apps targeting Android 15.

Lebar TextView berubah untuk bentuk huruf yang kompleks

Pada versi Android sebelumnya, beberapa font atau bahasa kursif yang memiliki bentuk kompleks dapat menggambar huruf di area karakter sebelumnya atau berikutnya. Dalam beberapa kasus, huruf tersebut dipangkas di posisi awal atau akhir. Mulai Android 15, TextView mengalokasikan lebar untuk menggambar ruang yang cukup untuk huruf tersebut dan memungkinkan aplikasi meminta padding tambahan ke kiri untuk mencegah pemangkasan.

Karena perubahan ini memengaruhi cara TextView menentukan lebar, TextView mengalokasikan lebih banyak lebar secara default jika aplikasi menargetkan Android 15 (level API 35) atau yang lebih baru. Anda dapat mengaktifkan atau menonaktifkan perilaku ini dengan memanggil setUseBoundsForWidth API di TextView.

Karena menambahkan padding kiri dapat menyebabkan ketidaksejajaran untuk tata letak yang ada, padding tidak ditambahkan secara default bahkan untuk aplikasi yang menargetkan Android 15 atau yang lebih tinggi. Namun, Anda dapat menambahkan padding tambahan untuk mencegah pemangkasan dengan memanggil setShiftDrawingOffsetForStartOverhang.

Contoh berikut menunjukkan bagaimana perubahan ini dapat meningkatkan tata letak teks untuk beberapa font dan bahasa.

Tata letak standar untuk teks bahasa Inggris dalam font kursif. Beberapa huruf terpotong. Berikut adalah XML yang sesuai:

<TextView
    android:fontFamily="cursive"
    android:text="java" />
Tata letak untuk teks bahasa Inggris yang sama dengan lebar dan padding tambahan. Berikut adalah XML yang sesuai:

<TextView
    android:fontFamily="cursive"
    android:text="java"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />
Tata letak standar untuk teks Thailand. Beberapa huruf diklip. Berikut XML yang sesuai:

<TextView
    android:text="คอมพิวเตอร์" />
Tata letak untuk teks Thai yang sama dengan lebar dan padding tambahan. Berikut XML yang sesuai:

<TextView
    android:text="คอมพิวเตอร์"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />

Tinggi baris default yang sesuai dengan lokalitas untuk EditText

Pada versi Android sebelumnya, tata letak teks meregangkan tinggi teks untuk memenuhi tinggi baris font yang cocok dengan lokalitas saat ini. Misalnya, jika konten dalam bahasa Jepang, karena tinggi baris font Jepang sedikit lebih besar dari font Latin, tinggi teks menjadi sedikit lebih besar. Namun, meskipun ada perbedaan tinggi baris ini, elemen EditText berukuran seragam, terlepas dari lokalitas yang digunakan, seperti yang diilustrasikan pada gambar berikut:

Tiga kotak yang mewakili elemen EditText yang dapat berisi teks dari bahasa Inggris (en), Jepang (ja), dan Burma (my). Tinggi EditText sama, meskipun bahasa ini memiliki tinggi baris yang berbeda satu sama lain.

Untuk aplikasi yang menargetkan Android 15 (API level 35), tinggi baris minimum kini disediakan untuk EditText agar cocok dengan font referensi untuk Lokalitas yang ditentukan, seperti yang ditunjukkan pada gambar berikut:

Tiga kotak yang mewakili elemen EditText yang dapat berisi teks dari bahasa Inggris (en), Jepang (ja), dan Burma (my). Tinggi EditText kini menyertakan ruang untuk mengakomodasi tinggi baris default untuk font bahasa ini.

Jika diperlukan, aplikasi Anda dapat memulihkan perilaku sebelumnya dengan menentukan atribut useLocalePreferredLineHeightForMinimum ke false, dan aplikasi Anda dapat menetapkan metrik vertikal minimum kustom menggunakan setMinimumFontMetrics API di Kotlin dan Java.

Kamera dan media

Android 15 membuat perubahan berikut pada perilaku kamera dan media untuk aplikasi yang menargetkan Android 15 atau yang lebih tinggi.

Batasan untuk meminta fokus audio

Aplikasi yang menargetkan Android 15 (API level 35) harus menjadi aplikasi teratas atau menjalankan layanan latar depan untuk meminta fokus audio. Jika aplikasi mencoba meminta fokus saat tidak memenuhi salah satu persyaratan ini, panggilan akan menampilkan AUDIOFOCUS_REQUEST_FAILED.

Anda dapat mempelajari fokus audio lebih lanjut di Mengelola fokus audio.

Pembatasan non-SDK yang diperbarui

Android 15 includes updated lists of restricted non-SDK interfaces based on collaboration with Android developers and the latest internal testing. Whenever possible, we make sure that public alternatives are available before we restrict non-SDK interfaces.

If your app does not target Android 15, some of these changes might not immediately affect you. However, while it's possible for your app to access some non-SDK interfaces depending on your app's target API level, using any non-SDK method or field always carries a high risk of breaking your app.

If you are unsure if your app uses non-SDK interfaces, you can test your app to find out. If your app relies on non-SDK interfaces, you should begin planning a migration to SDK alternatives. Nevertheless, we understand that some apps have valid use cases for using non-SDK interfaces. If you can't find an alternative to using a non-SDK interface for a feature in your app, you should request a new public API.

Untuk mempelajari perubahan dalam rilis Android ini lebih lanjut, baca Pembaruan pembatasan antarmuka non-SDK di Android 15. Untuk mempelajari lebih lanjut antarmuka non-SDK secara umum, baca Pembatasan antarmuka non-SDK.