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 menargetkan Android 15 atau yang lebih tinggi, Anda harus memodifikasi aplikasi untuk mendukung perilaku ini dengan benar, jika memungkinkan.

Selain itu, pastikan Anda 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

Kami membuat perubahan berikut pada layanan latar depan dengan Android 15.

Perilaku waktu tunggu layanan latar depan sinkronisasi data

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 yang 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 dengan 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 memudahkan 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

Jenis layanan latar depan pemrosesan media baru

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

Pembatasan pada BOOT_COMPLETED penerima siaran yang meluncurkan layanan latar depan

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

Pembatasan dalam memulai layanan latar depan saat aplikasi memiliki izin SYSTEM_ALERT_WINDOW

Previously, if an app held the SYSTEM_ALERT_WINDOW permission, it could launch a foreground service even if the app was currently in the background (as discussed in exemptions from background start restrictions).

If an app targets Android 15, this exemption is now narrower. The app now needs to have the SYSTEM_ALERT_WINDOW permission and also have a visible overlay window. That is, the app needs to first launch a TYPE_APPLICATION_OVERLAY window and the window needs to be visible before you start a foreground service.

If your app attempts to start a foreground service from the background without meeting these new requirements (and it does not have some other exemption), the system throws ForegroundServiceStartNotAllowedException.

If your app declares the SYSTEM_ALERT_WINDOW permission and launches foreground services from the background, it may be affected by this change. If your app gets a ForegroundServiceStartNotAllowedException, check your app's order of operations and make sure your app already has an active overlay window before it attempts to start a foreground service from the background. You can check if your overlay window is currently visible by calling View.getWindowVisibility(), or you can override View.onWindowVisibilityChanged() to get notified whenever the visibility changes.

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). To enable these new restrictions on starting foreground services from the background, run the following adb command:

adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name

Perubahan terkait kapan aplikasi dapat mengubah status global mode Jangan Ganggu

Aplikasi yang menargetkan Android 15 tidak dapat lagi mengubah status global atau kebijakan Jangan Ganggu (DND) di perangkat (baik dengan mengubah setelan pengguna atau menonaktifkan mode DND). Sebagai gantinya, aplikasi harus memberikan kontribusi AutomaticZenRule, yang digabungkan oleh sistem ke dalam kebijakan global dengan skema yang paling ketat-kebijakan-kemenangan yang sudah ada. Panggilan ke API yang ada dan sebelumnya memengaruhi status global (setInterruptionFilter, setNotificationPolicy) menyebabkan pembuatan atau pembaruan AutomaticZenRule implisit, yang diaktifkan dan dinonaktifkan bergantung pada siklus panggilan panggilan API tersebut.

Perlu diperhatikan bahwa perubahan ini hanya memengaruhi perilaku yang dapat diamati jika aplikasi memanggil setInterruptionFilter(INTERRUPTION_FILTER_ALL) dan mengharapkan panggilan tersebut menonaktifkan AutomaticZenRule yang sebelumnya diaktifkan oleh pemiliknya.

Perubahan OpenJDK API

Android 15 continues the work of refreshing Android's core libraries to align with the features in the latest OpenJDK LTS releases.

Some of these changes can affect app compatibility for apps targeting Android 15 (API level 35):

  • Changes to string formatting APIs: Validation of argument index, flags, width, and precision are now more strict when using the following String.format() and Formatter.format() APIs:

    For example, the following exception is thrown when an argument index of 0 is used (%0 in the format string):

    IllegalFormatArgumentIndexException: Illegal format argument index = 0
    

    In this case, the issue can be fixed by using an argument index of 1 (%1 in the format string).

  • Changes to component type of Arrays.asList(...).toArray(): When using Arrays.asList(...).toArray(), the component type of the resulting array is now an Object—not the type of the underlying array's elements. So the following code throws a ClassCastException:

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

    For this case, to preserve String as the component type in the resulting array, you could use Collection.toArray(Object[]) instead:

    String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
    
  • Changes to language code handling: When using the Locale API, language codes for Hebrew, Yiddish, and Indonesian are no longer converted to their obsolete forms (Hebrew: iw, Yiddish: ji, and Indonesian: in). When specifying the language code for one of these locales, use the codes from ISO 639-1 instead (Hebrew: he, Yiddish: yi, and Indonesian: id).

  • Changes to random int sequences: Following the changes made in https://bugs.openjdk.org/browse/JDK-8301574, the following Random.ints() methods now return a different sequence of numbers than the Random.nextInt() methods do:

    Generally, this change shouldn't result in app-breaking behavior, but your code shouldn't expect the sequence generated from Random.ints() methods to match Random.nextInt().

The new SequencedCollection API can affect your app's compatibility after you update compileSdk in your app's build configuration to use Android 15 (API level 35):

  • Collision with MutableList.removeFirst() and MutableList.removeLast() extension functions in kotlin-stdlib

    The List type in Java is mapped to the MutableList type in Kotlin. Because the List.removeFirst() and List.removeLast() APIs have been introduced in Android 15 (API level 35), the Kotlin compiler resolves function calls, for example list.removeFirst(), statically to the new List APIs instead of to the extension functions in kotlin-stdlib.

    If an app is re-compiled with compileSdk set to 35 and minSdk set to 34 or lower, and then the app is run on Android 14 and lower, a runtime error is thrown:

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

    The existing NewApi lint option in Android Gradle Plugin can catch these new API usages.

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

    To fix the runtime exception and lint errors, the removeFirst() and removeLast() function calls can be replaced with removeAt(0) and removeAt(list.lastIndex) respectively in Kotlin. If you're using Android Studio Ladybug | 2024.1.3 or higher, it also provides a quick fix option for these errors.

    Consider removing @SuppressLint("NewApi") and lintOptions { disable 'NewApi' } if the lint option has been disabled.

  • Collision with other methods in Java

    New methods have been added into the existing types, for example, List and Deque. These new methods might not be compatible with the methods with the same name and argument types in other interfaces and classes. In the case of a method signature collision with incompatibility, the javac compiler outputs a build-time error. For example:

    Example 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
    

    Example 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
    

    Example 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
    

    To fix these build errors, the class implementing these interfaces should override the method with a compatible return type. For example:

    @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.

Peluncuran aktivitas latar belakang yang aman

Android 15 melindungi pengguna dari aplikasi berbahaya dan memberi pengguna kontrol yang lebih besar perangkat mereka dengan menambahkan perubahan yang mencegah aplikasi latar belakang berbahaya membawa aplikasi lain ke latar depan, meningkatkan hak istimewanya, dan menyalahgunakan interaksi pengguna. Peluncuran aktivitas latar belakang dibatasi sejak Android 10 (level API 29).

Blokir aplikasi yang tidak cocok dengan UID teratas pada tumpukan agar tidak meluncurkan aktivitas

Aplikasi berbahaya bisa meluncurkan aktivitas aplikasi lain dalam tugas yang sama, lalu menempatkan diri di atasnya, menciptakan ilusi sebagai aplikasi. "Tugas ini pembajakan" serangan menghindari pembatasan peluncuran di latar belakang saat ini karena semuanya muncul dalam tugas terlihat yang sama. Untuk memitigasi risiko ini, Android 15 menambahkan penanda yang memblokir aplikasi yang tidak cocok dengan UID teratas pada tumpukan agar tidak diluncurkan aktivitas Anda. Untuk ikut serta dalam semua aktivitas aplikasi Anda, perbarui allowCrossUidActivitySwitchFromBelow di file AndroidManifest.xml aplikasi Anda:

<application android:allowCrossUidActivitySwitchFromBelow="false" >

Langkah-langkah keamanan baru akan aktif jika semua hal berikut terpenuhi:

  • Aplikasi yang melakukan peluncuran menargetkan Android 15.
  • Aplikasi di atas tumpukan tugas menargetkan Android 15.
  • Semua aktivitas yang terlihat telah diikutsertakan ke perlindungan baru

Jika langkah-langkah keamanan diaktifkan, aplikasi mungkin akan dikembalikan ke beranda, bukan aplikasi yang terakhir terlihat, jika mereka menyelesaikan tugas mereka sendiri.

Perubahan lainnya

Selain pembatasan untuk pencocokan UID, perubahan lain ini juga termasuk:

  • Ubah PendingIntent kreator untuk memblokir peluncuran aktivitas latar belakang dengan default. Hal ini membantu mencegah aplikasi secara tidak sengaja membuat PendingIntent yang dapat disalahgunakan oleh pelaku kejahatan.
  • Jangan memindahkan aplikasi ke latar depan kecuali jika pengirim PendingIntent mengizinkannya. Perubahan ini bertujuan untuk mencegah aplikasi berbahaya menyalahgunakan kemampuan untuk memulai aktivitas di latar belakang. Secara default, aplikasi tidak diizinkan untuk memindahkan stack tugas ke latar depan kecuali jika kreator mengizinkan hak istimewa peluncuran aktivitas latar belakang atau pengirim memiliki aktivitas latar belakang hak istimewa peluncuran.
  • Kontrol cara aktivitas teratas tumpukan tugas dapat menyelesaikan tugasnya. Jika aktivitas teratas yang menyelesaikan tugas, Android akan kembali ke tugas mana pun yang terakhir aktif. Selain itu, jika aktivitas non-top menyelesaikan tugasnya, Android akan kembali ke layar beranda; itu tidak akan memblokir penyelesaian non-top ini aktivitas Anda.
  • Mencegah peluncuran aktivitas arbitrer dari aplikasi lain ke aplikasi Anda sendiri tugas. Perubahan ini mencegah aplikasi berbahaya melakukan phishing pengguna dengan membuat aktivitas yang tampaknya berasal dari aplikasi lain.
  • Memblokir jendela yang tidak terlihat agar tidak dipertimbangkan untuk aktivitas latar belakang peluncuran. Tindakan ini membantu mencegah aplikasi berbahaya menyalahgunakan latar belakang peluncuran aktivitas untuk menampilkan konten yang tidak diinginkan atau berbahaya kepada pengguna.

Intent yang lebih aman

Android 15 memperkenalkan langkah-langkah keamanan opsional baru untuk membuat intent lebih aman dan lebih andal. 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:

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

Untuk memeriksa respons aplikasi Anda terhadap perubahan ini, gunakan StrictMode di aplikasi Anda. Untuk melihat log mendetail 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

Ada dua perubahan terkait inset jendela di Android 15: tata letak layar penuh diterapkan secara default, dan ada juga perubahan konfigurasi, seperti konfigurasi default kolom sistem.

Penerapan menyeluruh

Aplikasi ditampilkan di 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 memiliki layar penuh di perangkat Android 15.


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

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

  • Menu navigasi handle gestur
    • Transparan secara default.
    • Offset bawah dinonaktifkan sehingga konten digambar di belakang menu navigasi sistem, kecuali jika inset diterapkan.
    • setNavigationBarColor dan R.attr#navigationBarColor tidak digunakan lagi dan tidak memengaruhi navigasi gestur.
    • setNavigationBarContrastEnforced dan R.attr#navigationBarContrastEnforced terus tidak berpengaruh pada navigasi gestur.
  • Navigasi 3 tombol
    • Opasitasnya 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 cocok dengan latar belakang jendela secara default. Latar belakang jendela harus berupa drawable warna agar default ini dapat diterapkan. API ini tidak digunakan lagi, tetapi terus memengaruhi navigasi 3 tombol.
    • setNavigationBarContrastEnforced dan R.attr#navigationBarContrastEnforced bernilai benar (true) secara default, yang menambahkan latar belakang buram 80% di 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 yang tidak mengambang harus 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 dari tepi ke tepi.

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

Aplikasi yang menargetkan Android 14 dan tidak memiliki layar penuh di perangkat Android 15.
Aplikasi yang menargetkan Android 15 (API level 35) dan memiliki tampilan penuh di perangkat Android 15. Namun, banyak elemen kini disembunyikan oleh panel status, panel 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 (API level 35), adalah layar penuh di perangkat Android 15 dan menerapkan inset agar UI tidak tersembunyi.
Hal yang perlu diperiksa jika aplikasi Anda sudah memenuhi seluruh layar

Jika aplikasi Anda sudah dari tepi ke tepi dan menerapkan inset, Anda sebagian besar tidak akan terpengaruh, kecuali dalam skenario berikut. Namun, meskipun Anda merasa tidak terpengaruh, sebaiknya uji aplikasi Anda.

  • Anda memiliki jendela yang tidak mengambang, seperti Activity yang menggunakan SHORT_EDGES, NEVER, atau DEFAULT, bukan LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS. Jika aplikasi Anda error saat diluncurkan, hal ini mungkin disebabkan oleh layar pembuka. Anda dapat mengupgrade dependensi layar utama ke 1.2.0-alpha01 atau yang lebih baru atau menetapkan window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always.
  • Mungkin ada layar dengan traffic lebih rendah yang memiliki UI yang terhalang. Pastikan layar yang kurang dikunjungi ini tidak memiliki UI yang terhalang. Layar dengan traffic lebih rendah mencakup:
    • Layar aktivasi atau login
    • Halaman setelan
Yang harus diperiksa jika aplikasi Anda belum memenuhi syarat untuk layar penuh

Jika aplikasi Anda belum layar penuh, kemungkinan besar Anda akan terpengaruh. Selain skenario untuk aplikasi yang sudah memiliki tampilan 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 secara 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 untuk 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, akan 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 berada dalam Scaffold, Anda dapat menggunakan inset menggunakan 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 apakah 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 menu navigasi 3 tombol atau WindowInsets.Type#statusBars.

Referensi edge-to-edge tambahan

Lihat panduan Tampilan Edge to Edge dan Compose Edge to Edge 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

If your app targets Android 15 (API level 35) or higher, Configuration no longer excludes the system bars. If you use the screen size in the Configuration class for layout calculation, you should replace it with better alternatives like an appropriate ViewGroup, WindowInsets, or WindowMetricsCalculator depending on your need.

Configuration has been available since API 1. It is typically obtained from Activity.onConfigurationChanged. It provides information like window density, orientation, and sizes. One important characteristic about the window sizes returned from Configuration is that it previously excluded the system bars.

The configuration size is typically used for resource selection, such as /res/layout-h500dp, and this is still a valid use case. However, using it for layout calculation has always been discouraged. If you do so, you should move away from it now. You should replace the use of Configuration with something more suitable depending on your use case.

If you use it to calculate the layout, use an appropriate ViewGroup, such as CoordinatorLayout or ConstraintLayout. If you use it to determine the height of the system navbar, use WindowInsets. If you want to know the current size of your app window, use computeCurrentWindowMetrics.

The following list describes the fields affected by this change:

Atribut elegantTextHeight defaultnya adalah true

Untuk aplikasi yang menargetkan Android 15, atribut elegantTextHeight TextView menjadi true secara default, yang menggantikan font ringkas yang digunakan secara default dengan beberapa skrip yang memiliki metrik vertikal besar dengan metrik yang jauh lebih mudah dibaca. Font ringkas diperkenalkan untuk mencegah tata letak rusak; Android 13 (API level 33) mencegah banyak kerusakan ini dengan memungkinkan tata letak teks meregangkan tinggi vertikal menggunakan atribut fallbackLineSpacing.

Di Android 15, font yang ringkas masih tetap ada di sistem sehingga aplikasi Anda dapat menetapkan elegantTextHeight ke false untuk mendapatkan perilaku yang sama seperti sebelumnya, tetapi mungkin tidak akan didukung dalam rilis mendatang. Jadi, jika aplikasi Anda mendukung skrip berikut: Arab, Lao, Myanmar, Tamil, Gujarati, Kannada, Malayalam, Odia, Telugu, atau Thailand, uji aplikasi Anda dengan menetapkan elegantTextHeight ke true.

Perilaku elegantTextHeight untuk aplikasi yang menargetkan Android 14 (API level 34) dan yang lebih rendah.
Perilaku elegantTextHeight untuk aplikasi yang menargetkan Android 15.

Perubahan lebar TextView 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 mempertimbangkan lokalitas untuk EditText

Pada versi Android sebelumnya, tata letak teks merentangkan tinggi teks untuk memenuhi tinggi baris font yang cocok dengan lokalitas saat ini. Misalnya, jika konten menggunakan bahasa Jepang, karena tinggi baris font Jepang sedikit lebih besar daripada salah satu font Latin, tinggi teks menjadi sedikit lebih besar. Namun, terlepas dari perbedaan tinggi baris ini, elemen EditText memiliki ukuran yang seragam, terlepas dari lokalitas yang digunakan, seperti yang diilustrasikan dalam 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, tinggi baris minimum sekarang 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 melakukan perubahan berikut pada perilaku kamera dan media untuk aplikasi yang menargetkan Android 15 atau yang lebih baru.

Batasan untuk meminta fokus audio

Aplikasi yang menargetkan Android 15 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 menyertakan daftar terbaru antarmuka non-SDK yang dibatasi berdasarkan kolaborasi dengan developer Android dan pengujian internal terbaru. Jika memungkinkan, kami akan memastikan ketersediaan alternatif publik sebelum membatasi antarmuka non-SDK.

Jika aplikasi Anda tidak menargetkan Android 15, beberapa perubahan ini mungkin tidak langsung memengaruhi Anda. Namun, meskipun aplikasi Anda dapat mengakses beberapa antarmuka non-SDK bergantung pada API level target aplikasi Anda, penggunaan metode atau kolom non-SDK selalu berisiko tinggi merusak aplikasi Anda.

Jika tidak yakin apakah aplikasi Anda menggunakan antarmuka non-SDK atau tidak, Anda dapat menguji aplikasi untuk mencari tahu. Jika aplikasi Anda mengandalkan antarmuka non-SDK, sebaiknya Anda mulai merencanakan migrasi ke alternatif SDK. Meskipun begitu, kami memahami bahwa beberapa aplikasi memiliki kasus penggunaan yang valid untuk menggunakan antarmuka non-SDK. Jika tidak dapat menemukan alternatif penggunaan antarmuka non-SDK untuk fitur dalam aplikasi Anda, sebaiknya minta API publik baru.

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.