Seperti rilis sebelumnya, Android 14 menyertakan perubahan perilaku yang mungkin memengaruhi aplikasi Anda. Perubahan perilaku berikut ini berlaku khusus bagi aplikasi yang menargetkan Android 14 (API level 34) atau yang lebih tinggi. Jika aplikasi menargetkan Android 14 atau yang lebih tinggi, Anda harus memodifikasi aplikasi untuk mendukung perilaku ini dengan benar, jika berlaku.
Selain itu, pastikan Anda meninjau daftar perubahan perilaku yang memengaruhi semua aplikasi
yang berjalan di Android 14, terlepas dari
targetSdkVersion
aplikasi tersebut.
Fungsi inti
Jenis layanan latar depan wajib diisi
Jika menargetkan Android 14 (API level 34) atau yang lebih tinggi, aplikasi harus menentukan setidaknya satu jenis layanan latar depan untuk setiap layanan latar depan dalam aplikasi Anda. Anda harus memilih jenis layanan latar depan yang mewakili kasus penggunaan aplikasi. Sistem mengharapkan layanan latar depan yang memiliki jenis tertentu untuk memenuhi kasus penggunaan tertentu.
Jika kasus penggunaan di aplikasi Anda tidak terkait dengan salah satu jenis ini, sebaiknya migrasikan logika untuk menggunakan WorkManager atau tugas transfer data yang dimulai pengguna
Penerapan izin BLUETOOTH_CONNECT di BluetoothAdapter
Android 14 menerapkan izin BLUETOOTH_CONNECT
saat memanggil
metode BluetoothAdapter
getProfileConnectionState()
untuk aplikasi yang menargetkan
Android 14 (API level 34) atau yang lebih tinggi.
Metode ini sudah memerlukan izin BLUETOOTH_CONNECT
, tetapi tidak
diterapkan. Pastikan aplikasi Anda mendeklarasikan BLUETOOTH_CONNECT
dalam file
AndroidManifest.xml
aplikasi seperti yang ditunjukkan dalam cuplikan berikut dan periksa apakah
pengguna telah memberikan izin sebelum memanggil
getProfileConnectionState
.
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
Update OpenJDK 17
Android 14 melanjutkan pekerjaan memuat ulang library inti Android agar selaras dengan fitur dalam rilis OpenJDK LTS terbaru, termasuk update library dan dukungan bahasa Java 17 untuk developer aplikasi dan platform.
Beberapa perubahan ini dapat memengaruhi kompatibilitas aplikasi:
- Perubahan pada ekspresi reguler: Referensi grup yang tidak valid kini
tidak diizinkan untuk mengikuti semantik OpenJDK lebih dekat. Anda mungkin melihat
kasus baru saat
IllegalArgumentException
ditampilkan oleh classjava.util.regex.Matcher
, jadi pastikan untuk menguji aplikasi Anda untuk area yang menggunakan ekspresi reguler. Untuk mengaktifkan atau menonaktifkan perubahan ini saat menguji, alihkan flagDISALLOW_INVALID_GROUP_REFERENCE
menggunakan alat framework kompatibilitas. - Penanganan UUID: Metode
java.util.UUID.fromString()
kini melakukan pemeriksaan yang lebih ketat saat memvalidasi argumen input, sehingga Anda mungkin melihatIllegalArgumentException
selama deserialisasi. Untuk mengaktifkan atau menonaktifkan perubahan ini saat menguji, alihkan flagENABLE_STRICT_VALIDATION
menggunakan alat framework kompatibilitas. - Masalah ProGuard: Dalam beberapa kasus, penambahan class
java.lang.ClassValue
menyebabkan masalah jika Anda mencoba untuk menyusutkan, meng-obfuscate, dan mengoptimalkan aplikasi menggunakan ProGuard. Masalah ini berasal dari library Kotlin yang mengubah perilaku runtime berdasarkan apakahClass.forName("java.lang.ClassValue")
menampilkan class atau tidak. Jika aplikasi Anda dikembangkan terhadap runtime versi lama tanpa classjava.lang.ClassValue
yang tersedia, pengoptimalan ini mungkin akan menghapus metodecomputeValue
dari class yang berasal darijava.lang.ClassValue
.
JobScheduler memperkuat perilaku callback dan jaringan
Sejak diperkenalkan, JobScheduler memperkirakan aplikasi akan ditampilkan dari
onStartJob
atau onStopJob
dalam beberapa detik. Sebelum Android 14,
jika tugas berjalan terlalu lama, tugas akan berhenti dan gagal secara otomatis. Jika aplikasi Anda menargetkan Android
14 (API level 34) atau yang lebih tinggi dan melebihi waktu yang diberikan di thread utama, aplikasi
akan memicu ANR dengan pesan error "Tidak ada respons ke onStartJob
" atau "Tidak
respons ke onStopJob
". Pertimbangkan untuk bermigrasi ke WorkManager, yang menyediakan
dukungan untuk pemrosesan asinkron atau memigrasikan pekerjaan berat apa pun ke
thread latar belakang.
JobScheduler
juga memperkenalkan persyaratan untuk mendeklarasikan
izin ACCESS_NETWORK_STATE
jika menggunakan batasan setRequiredNetworkType
atau
setRequiredNetwork
. Jika aplikasi Anda tidak mendeklarasikan
izin ACCESS_NETWORK_STATE
saat menjadwalkan tugas dan menargetkan
Android 14 atau yang lebih tinggi, aplikasi akan menghasilkan SecurityException
.
API peluncuran Kartu
Untuk aplikasi yang menargetkan versi 14 dan yang lebih tinggi,
TileService#startActivityAndCollapse(Intent)
tidak digunakan lagi dan kini menampilkan
pengecualian saat dipanggil. Jika aplikasi Anda meluncurkan aktivitas dari kartu, gunakan
TileService#startActivityAndCollapse(PendingIntent)
.
Privasi
Akses sebagian ke foto dan video
Android 14 memperkenalkan Akses Foto yang Dipilih, yang memungkinkan pengguna memberikan akses ke gambar dan video tertentu di galeri foto mereka, bukan memberikan akses ke semua media dari jenis tertentu.
Perubahan ini hanya diaktifkan jika aplikasi Anda menargetkan Android 14 (API level 34) atau yang lebih tinggi. Jika Anda belum menggunakan pemilih foto, sebaiknya terapkan di aplikasi Anda untuk memberikan pengalaman yang konsisten saat memilih gambar dan video yang juga meningkatkan privasi pengguna tanpa harus meminta izin penyimpanan apa pun.
Jika Anda mengelola alat pilih galeri sendiri menggunakan izin penyimpanan dan perlu
memiliki kontrol penuh atas penerapan Anda, sesuaikan penerapan Anda
untuk menggunakan izin READ_MEDIA_VISUAL_USER_SELECTED
yang baru. Jika aplikasi
tidak menggunakan izin baru, sistem akan menjalankan aplikasi dalam mode
kompatibilitas.
Pengalaman pengguna
Notifikasi Intent layar penuh yang aman
Dengan Android 11 (level API 30), aplikasi apa pun dapat menggunakan
Notification.Builder.setFullScreenIntent
untuk mengirim intent
layar penuh saat ponsel terkunci. Anda dapat memberikannya secara otomatis saat penginstalan aplikasi dengan
mendeklarasikan izin USE_FULL_SCREEN_INTENT
di
AndroidManifest.
Notifikasi intent layar penuh dirancang untuk notifikasi dengan prioritas sangat tinggi
yang meminta perhatian segera pengguna, seperti setelan
panggilan telepon masuk atau jam alarm yang dikonfigurasi oleh pengguna. Untuk aplikasi yang menargetkan
Android 14 (API level 34) atau yang lebih tinggi, aplikasi yang diizinkan untuk menggunakan izin
ini terbatas pada aplikasi yang hanya menyediakan panggilan dan alarm. Google
Play Store mencabut izin USE_FULL_SCREEN_INTENT
default untuk aplikasi
apa pun yang tidak sesuai dengan profil ini. Batas waktu untuk perubahan kebijakan ini adalah 31 Mei
2024.
Izin ini tetap diaktifkan untuk aplikasi yang diinstal di ponsel sebelum pengguna mengupdate ke Android 14. Pengguna dapat mengaktifkan dan menonaktifkan izin ini.
Anda dapat menggunakan API baru
NotificationManager.canUseFullScreenIntent
untuk memeriksa apakah aplikasi
memiliki izin. Jika tidak, aplikasi Anda dapat menggunakan intent baru
ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT
untuk meluncurkan halaman
setelan tempat pengguna dapat memberikan izin.
Keamanan
Pembatasan ke intent yang implisit dan tertunda
Untuk aplikasi yang menargetkan Android 14 (API level 34) atau yang lebih tinggi, Android membatasi aplikasi agar tidak mengirim intent implisit ke komponen aplikasi internal dengan cara berikut:
- Intent implisit hanya dikirim ke komponen yang diekspor. Aplikasi harus menggunakan intent eksplisit untuk mengirim ke komponen yang tidak diekspor, atau menandai komponen sebagai diekspor.
- Jika aplikasi membuat intent tertunda yang dapat berubah dengan intent yang tidak menentukan komponen atau paket, sistem akan menampilkan pengecualian.
Perubahan ini mencegah aplikasi berbahaya agar tidak mencegat intent implisit yang dimaksudkan untuk digunakan oleh komponen internal aplikasi.
Misalnya, berikut ini filter intent yang dapat dideklarasikan dalam file manifes aplikasi:
<activity
android:name=".AppActivity"
android:exported="false">
<intent-filter>
<action android:name="com.example.action.APP_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Jika aplikasi Anda mencoba meluncurkan aktivitas ini menggunakan intent implisit, pengecualian akan ditampilkan:
Kotlin
// Throws an exception when targeting Android 14. context.startActivity(Intent("com.example.action.APP_ACTION"))
Java
// Throws an exception when targeting Android 14. context.startActivity(new Intent("com.example.action.APP_ACTION"));
Untuk meluncurkan aktivitas yang tidak diekspor, aplikasi Anda harus menggunakan intent eksplisit:
Kotlin
// This makes the intent explicit. val explicitIntent = Intent("com.example.action.APP_ACTION") explicitIntent.apply { package = context.packageName } context.startActivity(explicitIntent)
Java
// This makes the intent explicit. Intent explicitIntent = new Intent("com.example.action.APP_ACTION") explicitIntent.setPackage(context.getPackageName()); context.startActivity(explicitIntent);
Penerima siaran yang terdaftar runtime harus menentukan perilaku ekspor
Aplikasi dan layanan yang menargetkan Android 14 (level API 34) atau yang lebih tinggi dan menggunakan
penerima yang terdaftar dalam konteks wajib menentukan tanda
untuk menunjukkan apakah penerima harus diekspor ke semua aplikasi lain di
perangkat: RECEIVER_EXPORTED
atau RECEIVER_NOT_EXPORTED
.
Persyaratan ini membantu melindungi aplikasi dari kerentanan keamanan dengan memanfaatkan
fitur untuk penerima ini yang diperkenalkan di Android 13.
Pengecualian untuk penerima yang hanya menerima siaran sistem
Jika aplikasi Anda mendaftarkan penerima hanya untuk
siaran sistem melalui metode
Context#registerReceiver
, seperti Context#registerReceiver()
, aplikasi
tidak boleh menentukan flag saat mendaftarkan penerima tersebut.
Pemuatan kode dinamis yang lebih aman
Jika aplikasi Anda menargetkan Android 14 (level API 34) atau yang lebih baru dan menggunakan Pemuatan Kode Dinamis (DCL), semua file yang dimuat secara dinamis harus ditandai sebagai hanya baca. Jika tidak, sistem akan menampilkan pengecualian. Sebaiknya aplikasi menghindari pemuatan kode secara dinamis jika memungkinkan, karena hal ini akan sangat meningkatkan risiko aplikasi disusupi oleh injeksi kode atau modifikasi kode.
Jika Anda harus memuat kode secara dinamis, gunakan pendekatan berikut untuk menetapkan file yang dimuat secara dinamis (seperti file DEX, JAR, atau APK) sebagai file hanya baca, segera setelah file dibuka dan sebelum konten apa pun ditulis:
Kotlin
val jar = File("DYNAMICALLY_LOADED_FILE.jar") val os = FileOutputStream(jar) os.use { // Set the file to read-only first to prevent race conditions jar.setReadOnly() // Then write the actual file content } val cl = PathClassLoader(jar, parentClassLoader)
Java
File jar = new File("DYNAMICALLY_LOADED_FILE.jar"); try (FileOutputStream os = new FileOutputStream(jar)) { // Set the file to read-only first to prevent race conditions jar.setReadOnly(); // Then write the actual file content } catch (IOException e) { ... } PathClassLoader cl = new PathClassLoader(jar, parentClassLoader);
Menangani file yang dimuat secara dinamis dan sudah ada
Agar pengecualian tidak ditampilkan untuk file yang dimuat secara dinamis dan sudah ada, sebaiknya hapus dan buat ulang file sebelum Anda mencoba lagi memuatnya secara dinamis di aplikasi Anda. Saat Anda membuat ulang file, ikuti panduan sebelumnya untuk menandai file sebagai hanya baca pada waktu penulisan. Atau, Anda dapat melabeli ulang file yang ada sebagai hanya baca, tetapi dalam kasus ini, kami sangat menyarankan Anda untuk memverifikasi integritas file terlebih dahulu (misalnya dengan memeriksa tanda tangan file terhadap nilai tepercaya) untuk membantu melindungi aplikasi Anda dari tindakan berbahaya.
Batasan tambahan dalam memulai aktivitas dari latar belakang
Untuk aplikasi yang menargetkan Android 14 (API level 34) atau yang lebih tinggi, sistem akan lebih membatasi kapan aplikasi diizinkan untuk memulai aktivitas dari latar belakang:
- Saat mengirim
PendingIntent
menggunakanPendingIntent#send()
atau metode serupa, aplikasi harus memilih ikut serta jika ingin memberikan hak istimewa peluncuran aktivitas latar belakangnya sendiri untuk memulai intent yang tertunda. Untuk ikut serta, aplikasi harus meneruskan paketActivityOptions
dengansetPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
. - Saat aplikasi yang terlihat mengikat layanan dari aplikasi lain yang ada di latar belakang
menggunakan metode
bindService()
, aplikasi yang terlihat kini harus memilih untuk ikut serta jika ingin memberikan hak istimewa peluncuran aktivitas latar belakangnya sendiri ke layanan terikat. Untuk ikut serta, aplikasi harus menyertakan flagBIND_ALLOW_ACTIVITY_STARTS
saat memanggil metodebindService()
.
Perubahan ini memperluas serangkaian pembatasan yang sudah ada untuk melindungi pengguna dengan mencegah aplikasi berbahaya menyalahgunakan API guna memulai aktivitas yang mengganggu dari latar belakang.
Zip path traversal
对于以 Android 14(API 级别 34)或更高版本为目标平台的应用,Android 会通过以下方式防止 Zip 路径遍历漏洞:如果 zip 文件条目名称包含“..”或以“/”开头,则 ZipInputStream.getNextEntry()
会抛出 ZipException
。ZipFile(String)
应用可以通过调用 dalvik.system.ZipPathValidator.clearCallback()
选择停用此验证。
Izin pengguna diperlukan untuk setiap sesi pengambilan MediaProjection
Untuk aplikasi yang menargetkan Android 14 (API level 34) atau yang lebih tinggi, SecurityException
ditampilkan oleh MediaProjection#createVirtualDisplay
dalam salah satu skenario
berikut:
- Aplikasi Anda meng-cache
Intent
yang ditampilkan dariMediaProjectionManager#createScreenCaptureIntent
, dan meneruskannya beberapa kali keMediaProjectionManager#getMediaProjection
. - Aplikasi Anda memanggil
MediaProjection#createVirtualDisplay
beberapa kali pada instanceMediaProjection
yang sama.
Aplikasi Anda harus meminta pengguna untuk memberikan izin sebelum setiap sesi pengambilan gambar. Sesi pengambilan tunggal adalah panggilan tunggal pada MediaProjection#createVirtualDisplay
, dan setiap instance MediaProjection
hanya boleh digunakan sekali.
Menangani perubahan konfigurasi
Jika aplikasi perlu memanggil MediaProjection#createVirtualDisplay
untuk menangani
perubahan konfigurasi (seperti orientasi layar atau perubahan ukuran layar),
Anda dapat mengikuti langkah-langkah berikut untuk mengupdate VirtualDisplay
untuk instance
MediaProjection
yang sudah ada:
- Panggil
VirtualDisplay#resize
dengan lebar dan tinggi yang baru. - Berikan
Surface
baru dengan lebar dan tinggi yang baru keVirtualDisplay#setSurface
.
Mendaftarkan callback
Aplikasi Anda harus mendaftarkan callback untuk menangani kasus saat pengguna tidak memberikan izin untuk melanjutkan sesi perekaman. Untuk melakukannya, implementasikan
Callback#onStop
dan minta aplikasi Anda merilis resource terkait (seperti
VirtualDisplay
dan Surface
).
Jika aplikasi Anda tidak mendaftarkan callback ini,
MediaProjection#createVirtualDisplay
akan menampilkan IllegalStateException
saat aplikasi memanggil callback tersebut.
Pembatasan non-SDK yang diperbarui
Android 14 包含更新后的受限非 SDK 接口列表(基于与 Android 开发者之间的协作以及最新的内部测试)。在限制使用非 SDK 接口之前,我们会尽可能确保有可用的公开替代方案。
如果您的应用并非以 Android 14 为目标平台,其中一些变更可能不会立即对您产生影响。然而,虽然您目前仍可以使用一些非 SDK 接口(具体取决于应用的目标 API 级别),但只要您使用任何非 SDK 方法或字段,终归存在导致应用出问题的显著风险。
如果您不确定自己的应用是否使用了非 SDK 接口,则可以测试您的应用来进行确认。如果您的应用依赖于非 SDK 接口,您应该开始计划迁移到 SDK 替代方案。然而,我们知道某些应用具有使用非 SDK 接口的有效用例。如果您无法为应用中的某项功能找到使用非 SDK 接口的替代方案,应请求新的公共 API。
Untuk mempelajari perubahan dalam rilis Android ini lebih lanjut, baca Pembaruan pembatasan antarmuka non-SDK di Android 14. Untuk mempelajari lebih lanjut antarmuka non-SDK secara umum, baca Pembatasan antarmuka non-SDK.