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 (level API 34) atau yang lebih baru. Jika aplikasi menargetkan Android 14 atau yang lebih tinggi, Anda harus memodifikasi aplikasi agar 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.
Fungsi inti
Jenis layanan latar depan wajib diisi
If your app targets Android 14 (API level 34) or higher, it must specify at least one foreground service type for each foreground service within your app. You should choose a foreground service type that represents your app's use case. The system expects foreground services that have a particular type to satisfy a particular use case.
If a use case in your app isn't associated with any of these types, it's strongly recommended that you migrate your logic to use WorkManager or user-initiated data transfer jobs.
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
Since its introduction, JobScheduler expects your app to return from
onStartJob
or onStopJob
within a few seconds. Prior to Android 14,
if a job runs too long, it stops and fails silently. If your app targets Android
14 (API level 34) or higher and exceeds the granted time on the main thread, the
app triggers an ANR with the error message "No response to onStartJob
" or "No
response to onStopJob
". Consider migrating to WorkManager, which provides
support for asynchronous processing or migrating any heavy work into a
background thread.
JobScheduler
also introduces a requirement to declare the
ACCESS_NETWORK_STATE
permission if using setRequiredNetworkType
or
setRequiredNetwork
constraint. If your app does not declare the
ACCESS_NETWORK_STATE
permission when scheduling the job and is targeting
Android 14 or higher, it will result in a 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 introduces Selected Photos Access, which allows users to grant apps access to specific images and videos in their library, rather than granting access to all media of a given type.
This change is only enabled if your app targets Android 14 (API level 34) or higher. If you don't use the photo picker yet, we recommend implementing it in your app to provide a consistent experience for selecting images and videos that also enhances user privacy without having to request any storage permissions.
If you maintain your own gallery picker using storage permissions and need to
maintain full control over your implementation, adapt your implementation
to use the new READ_MEDIA_VISUAL_USER_SELECTED
permission. If your app
doesn't use the new permission, the system runs your app in a compatibility
mode.
Pengalaman pengguna
Notifikasi Intent layar penuh yang aman
With Android 11 (API level 30), it was possible for any app to use
Notification.Builder.setFullScreenIntent
to send full-screen
intents while the phone is locked. You could auto-grant this on app install by
declaring USE_FULL_SCREEN_INTENT
permission in the
AndroidManifest.
Full-screen intent notifications are designed for extremely high-priority
notifications demanding the user's immediate attention, such as an incoming
phone call or alarm clock settings configured by the user. For apps targeting
Android 14 (API level 34) or higher, apps that are allowed to use this
permission are limited to those that provide calling and alarms only. The Google
Play Store revokes default USE_FULL_SCREEN_INTENT
permissions for any apps
that don't fit this profile. The deadline for these policy changes is May 31,
2024.
This permission remains enabled for apps installed on the phone before the user updates to Android 14. Users can turn this permission on and off.
You can use the new API
NotificationManager.canUseFullScreenIntent
to check if your app
has the permission; if not, your app can use the new intent
ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT
to launch the settings
page where users can grant the permission.
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
Apps and services that target Android 14 (API level 34) or higher and use
context-registered receivers are required to specify a flag
to indicate whether or not the receiver should be exported to all other apps on
the device: either RECEIVER_EXPORTED
or RECEIVER_NOT_EXPORTED
, respectively.
This requirement helps protect apps from security vulnerabilities by leveraging
the features for these receivers introduced in Android 13.
Exception for receivers that receive only system broadcasts
If your app is registering a receiver only for
system broadcasts through Context#registerReceiver
methods, such as Context#registerReceiver()
, then it
shouldn't specify a flag when registering the receiver.
Pemuatan kode dinamis yang lebih aman
If your app targets Android 14 (API level 34) or higher and uses Dynamic Code Loading (DCL), all dynamically-loaded files must be marked as read-only. Otherwise, the system throws an exception. We recommend that apps avoid dynamically loading code whenever possible, as doing so greatly increases the risk that an app can be compromised by code injection or code tampering.
If you must dynamically load code, use the following approach to set the dynamically-loaded file (such as a DEX, JAR, or APK file) as read-only as soon as the file is opened and before any content is written:
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);
Handle dynamically-loaded files that already exist
To prevent exceptions from being thrown for existing dynamically-loaded files, we recommend deleting and recreating the files before you try to dynamically load them again in your app. As you recreate the files, follow the preceding guidance for marking the files read-only at write time. Alternatively, you can re-label the existing files as read-only, but in this case, we strongly recommend that you verify the integrity of the files first (for example, by checking the file's signature against a trusted value), to help protect your app from malicious actions.
Batasan tambahan dalam memulai aktivitas dari latar belakang
For apps targeting Android 14 (API level 34) or higher, the system further restricts when apps are allowed to start activities from the background:
- When an app sends a
PendingIntent
usingPendingIntent#send()
or similar methods, the app must opt in if it wants to grant its own background activity launch privileges to start the pending intent. To opt in, the app should pass anActivityOptions
bundle withsetPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
. - When a visible app binds a service of another app that's in the background
using the
bindService()
method, the visible app must now opt in if it wants to grant its own background activity launch privileges to the bound service. To opt in, the app should include theBIND_ALLOW_ACTIVITY_STARTS
flag when calling thebindService()
method.
These changes expand the existing set of restrictions to protect users by preventing malicious apps from abusing APIs to start disruptive activities from the background.
Zip path traversal
For apps targeting Android 14 (API level 34) or higher, Android prevents the Zip
Path Traversal Vulnerability in the following way:
ZipFile(String)
and
ZipInputStream.getNextEntry()
throws a
ZipException
if zip file entry names contain ".." or start
with "/".
Apps can opt-out from this validation by calling
dalvik.system.ZipPathValidator.clearCallback()
.
Izin pengguna diperlukan untuk setiap sesi pengambilan MediaProjection
For apps targeting Android 14 (API level 34) or higher, a SecurityException
is
thrown by MediaProjection#createVirtualDisplay
in either of the following
scenarios:
- Your app caches the
Intent
that is returned fromMediaProjectionManager#createScreenCaptureIntent
, and passes it multiple times toMediaProjectionManager#getMediaProjection
. - Your app invokes
MediaProjection#createVirtualDisplay
multiple times on the sameMediaProjection
instance.
Your app must ask the user to give consent before each capture session. A single
capture session is a single invocation on
MediaProjection#createVirtualDisplay
, and each MediaProjection
instance must
be used only once.
Handle configuration changes
If your app needs to invoke MediaProjection#createVirtualDisplay
to handle
configuration changes (such as the screen orientation or screen size changing),
you can follow these steps to update the VirtualDisplay
for the existing
MediaProjection
instance:
- Invoke
VirtualDisplay#resize
with the new width and height. - Provide a new
Surface
with the new width and height toVirtualDisplay#setSurface
.
Register a callback
Your app should register a callback to handle cases where the user doesn't grant
consent to continue a capture session. To do this, implement
Callback#onStop
and have your app release any related resources (such as
the VirtualDisplay
and Surface
).
If your app doesn't register this callback,
MediaProjection#createVirtualDisplay
throws an IllegalStateException
when your app invokes it.
Pembatasan non-SDK yang diperbarui
Android 14 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 14, some of these changes might not immediately affect you. However, while you can currently use 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 cannot 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 14. Untuk mempelajari lebih lanjut antarmuka non-SDK secara umum, baca Pembatasan antarmuka non-SDK.