Giống như các bản phát hành trước, Android 15 có các thay đổi về hành vi có thể ảnh hưởng đến ứng dụng của bạn. Những thay đổi về hành vi sau đây chỉ áp dụng cho ứng dụng nhắm đến Android 15 trở lên. Nếu ứng dụng của bạn nhắm đến Android 15 trở lên, bạn nên điều chỉnh ứng dụng để hỗ trợ những hành vi này cho phù hợp (nếu cần).
Ngoài ra, hãy nhớ tham khảo danh sách các thay đổi về hành vi ảnh hưởng đến tất cả ứng dụng chạy trên Android 15 bất kể targetSdkVersion
của ứng dụng.
Chức năng cốt lõi
Android 15 sửa đổi hoặc mở rộng nhiều chức năng cốt lõi của hệ thống Android.
Thay đổi đối với dịch vụ trên nền trước
Chúng tôi sẽ thực hiện những thay đổi sau đây đối với các dịch vụ trên nền trước trong Android 15.
- Hành vi hết thời gian chờ của dịch vụ đồng bộ hoá dữ liệu trên nền trước
- Loại dịch vụ trên nền trước mới để xử lý nội dung nghe nhìn
- Các hạn chế đối với bộ thu phát sóng
BOOT_COMPLETED
khởi chạy dịch vụ trên nền trước - Các hạn chế khi khởi động dịch vụ trên nền trước trong khi ứng dụng có quyền
SYSTEM_ALERT_WINDOW
Hành vi hết thời gian chờ của dịch vụ đồng bộ hoá dữ liệu trên nền trước
Android 15 giới thiệu một hành vi hết thời gian chờ mới cho dataSync
đối với các ứng dụng nhắm đến Android 15 (API cấp 35) trở lên. Hành vi này cũng áp dụng cho loại dịch vụ trên nền trước mediaProcessing
mới.
Hệ thống cho phép các dịch vụ dataSync
của ứng dụng chạy tổng cộng 6 giờ trong khoảng thời gian 24 giờ. Sau đó, hệ thống sẽ gọi phương thức Service.onTimeout(int, int)
của dịch vụ đang chạy (được giới thiệu trong Android 15). Tại thời điểm này, dịch vụ có vài giây để gọi Service.stopSelf()
. Khi Service.onTimeout()
được gọi, dịch vụ này không còn được coi là dịch vụ trên nền trước. Nếu dịch vụ không gọi Service.stopSelf()
, hệ thống sẽ gửi một ngoại lệ nội bộ. Ngoại lệ được ghi lại trong Logcat với thông báo sau:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"
Để tránh các vấn đề liên quan đến thay đổi về hành vi này, bạn có thể làm một hoặc nhiều việc sau:
- Yêu cầu dịch vụ triển khai phương thức
Service.onTimeout(int, int)
mới. Khi ứng dụng của bạn nhận được lệnh gọi lại, hãy nhớ gọistopSelf()
trong vài giây. (Nếu bạn không dừng ứng dụng ngay lập tức, hệ thống sẽ tạo lỗi.) - Đảm bảo các dịch vụ
dataSync
của ứng dụng không chạy quá tổng cộng 6 giờ trong khoảng thời gian 24 giờ bất kỳ (trừ phi người dùng tương tác với ứng dụng, đặt lại bộ tính giờ). - Chỉ bắt đầu dịch vụ trên nền trước
dataSync
do người dùng tương tác trực tiếp; vì ứng dụng của bạn đang ở nền trước khi dịch vụ bắt đầu, nên dịch vụ của bạn có đủ 6 giờ sau khi ứng dụng chuyển sang chế độ nền. - Thay vì sử dụng dịch vụ trên nền trước
dataSync
, hãy sử dụng API thay thế.
Nếu các dịch vụ trên nền trước dataSync
của ứng dụng đã chạy trong 6 giờ trong 24 giờ qua, thì bạn không thể bắt đầu một dịch vụ trên nền trước dataSync
khác trừ phi người dùng đã đưa ứng dụng của bạn lên nền trước (điều này sẽ đặt lại bộ hẹn giờ). Nếu bạn cố gắng khởi động một dịch vụ trên nền trước dataSync
khác, hệ thống sẽ gửi ForegroundServiceStartNotAllowedException
kèm theo thông báo lỗi như "Đã hết thời gian giới hạn cho loại dịch vụ trên nền trước dataSync".
Thử nghiệm
Để kiểm thử hành vi của ứng dụng, bạn có thể bật thời gian chờ đồng bộ hoá dữ liệu ngay cả khi ứng dụng không nhắm đến Android 15 (miễn là ứng dụng đang chạy trên thiết bị Android 15). Để bật thời gian chờ, hãy chạy lệnh adb
sau:
adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name
Bạn cũng có thể điều chỉnh khoảng thời gian chờ để dễ dàng kiểm thử cách ứng dụng của bạn hoạt động khi đạt đến giới hạn. Để đặt khoảng thời gian chờ mới, hãy chạy lệnh adb
sau:
adb shell device_config put activity_manager data_sync_fgs_timeout_duration duration-in-milliseconds
Loại dịch vụ trên nền trước mới để xử lý nội dung nghe nhìn
Android 15 giới thiệu một loại dịch vụ trên nền trước mới, mediaProcessing
. Loại dịch vụ này phù hợp với các thao tác như chuyển mã tệp phương tiện. Ví dụ: một ứng dụng đa phương tiện có thể tải tệp âm thanh xuống và cần chuyển đổi tệp đó sang một định dạng khác trước khi phát. Bạn có thể sử dụng dịch vụ trên nền trước mediaProcessing
để đảm bảo quá trình chuyển đổi sẽ tiếp tục ngay cả khi ứng dụng đang chạy trong nền.
Hệ thống cho phép các dịch vụ mediaProcessing
của ứng dụng chạy tổng cộng 6 giờ trong khoảng thời gian 24 giờ, sau đó hệ thống sẽ gọi phương thức Service.onTimeout(int, int)
của dịch vụ đang chạy (được giới thiệu trong Android 15). Tại thời điểm này, dịch vụ có vài giây để gọi Service.stopSelf()
. Nếu dịch vụ không gọi Service.stopSelf()
, hệ thống sẽ gửi một ngoại lệ nội bộ. Ngoại lệ được ghi lại trong Logcat với thông báo sau:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"
Để tránh trường hợp ngoại lệ này, bạn có thể làm theo một trong những cách sau:
- Yêu cầu dịch vụ của bạn triển khai phương thức
Service.onTimeout(int, int)
mới. Khi ứng dụng của bạn nhận được lệnh gọi lại, hãy nhớ gọistopSelf()
trong vòng vài giây. (Nếu bạn không dừng ứng dụng ngay lập tức, hệ thống sẽ tạo lỗi.) - Đảm bảo các dịch vụ
mediaProcessing
của ứng dụng không chạy quá tổng cộng 6 giờ trong khoảng thời gian 24 giờ bất kỳ (trừ phi người dùng tương tác với ứng dụng, đặt lại bộ tính giờ). - Chỉ bắt đầu dịch vụ trên nền trước
mediaProcessing
do người dùng tương tác trực tiếp; vì ứng dụng của bạn đang ở nền trước khi dịch vụ bắt đầu, nên dịch vụ của bạn có đủ 6 giờ sau khi ứng dụng chuyển sang chế độ nền. - Thay vì dùng dịch vụ trên nền trước
mediaProcessing
, hãy dùng một API thay thế, chẳng hạn như WorkManager.
Nếu các dịch vụ trên nền trước mediaProcessing
của ứng dụng đã chạy được 6 giờ trong 24 ngày qua, thì bạn không thể bắt đầu một dịch vụ trên nền trước mediaProcessing
khác trừ phi người dùng đã đưa ứng dụng của bạn lên nền trước (việc này đặt lại bộ tính giờ). Nếu bạn cố gắng bắt đầu một dịch vụ trên nền trước mediaProcessing
khác, hệ thống sẽ gửi ForegroundServiceStartNotAllowedException
kèm theo thông báo lỗi như "Hết thời gian giới hạn cho loại dịch vụ trên nền trước mediaProcessing".
Để biết thêm thông tin về loại dịch vụ mediaProcessing
, hãy xem phần Thay đổi đối với loại dịch vụ trên nền trước cho Android 15: Xử lý nội dung nghe nhìn.
Thử nghiệm
Để kiểm thử hành vi của ứng dụng, bạn có thể bật thời gian chờ xử lý nội dung nghe nhìn ngay cả khi ứng dụng của bạn không nhắm đến Android 15 (miễn là ứng dụng đang chạy trên thiết bị Android 15). Để bật tính năng thời gian chờ, hãy chạy lệnh adb
sau:
adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name
Bạn cũng có thể điều chỉnh khoảng thời gian chờ để dễ dàng kiểm thử cách ứng dụng của bạn hoạt động khi đạt đến giới hạn. Để đặt khoảng thời gian chờ mới, hãy chạy lệnh adb
sau:
adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds
Các hạn chế đối với bộ nhận thông báo truyền tin BOOT_COMPLETED
khởi chạy dịch vụ trên nền trước
在启动 BOOT_COMPLETED
广播接收器方面存在新限制
前台服务。BOOT_COMPLETED
接收器不能启动
以下类型的前台服务:
dataSync
camera
mediaPlayback
phoneCall
mediaProjection
microphone
(自 Android 14 起,microphone
就受到此限制)
如果 BOOT_COMPLETED
接收器尝试启动任何上述类型的前台
服务,系统会抛出 ForegroundServiceStartNotAllowedException
。
测试
如需测试应用的行为,您可以启用这些新限制,即使您的应用并未以 Android 15 为目标平台(只要应用在 Android 15 设备上运行)也是如此。运行以下 adb
命令:
adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name
如需在不重启设备的情况下发送 BOOT_COMPLETED
广播,请运行以下 adb
命令:
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED your-package-name
Các hạn chế về việc khởi động dịch vụ trên nền trước khi ứng dụng có quyền SYSTEM_ALERT_WINDOW
以前,如果应用拥有 SYSTEM_ALERT_WINDOW
权限,即使应用当前在后台运行,也可以启动前台服务(如免于后台启动限制中所述)。
如果应用以 Android 15 为目标平台,则此豁免范围现在更窄。现在,应用需要具有 SYSTEM_ALERT_WINDOW
权限,并且还需要有一个可见的叠加窗口。也就是说,应用需要先启动 TYPE_APPLICATION_OVERLAY
窗口,并且该窗口需要处于可见状态,然后您才能启动前台服务。
如果您的应用尝试从后台启动前台服务,但不符合这些新要求(并且没有其他豁免情况),系统会抛出 ForegroundServiceStartNotAllowedException
。
如果您的应用声明了 SYSTEM_ALERT_WINDOW
权限并从后台启动前台服务,则可能会受到此变更的影响。如果您的应用获得了 ForegroundServiceStartNotAllowedException
,请检查应用的操作顺序,并确保应用在尝试从后台启动前台服务之前已具有有效的叠加层窗口。您可以通过调用 View.getWindowVisibility()
检查叠加层窗口当前是否可见,也可以替换 View.onWindowVisibilityChanged()
,以便在可见性发生变化时收到通知。
测试
如需测试应用的行为,您可以启用这些新限制,即使您的应用并未以 Android 15 为目标平台(只要应用在 Android 15 设备上运行)也是如此。如需针对从后台启动前台服务启用这些新限制,请运行以下 adb
命令:
adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name
Những thay đổi về thời điểm các ứng dụng có thể sửa đổi trạng thái chung của chế độ Không làm phiền
Các ứng dụng nhắm đến Android 15 (API cấp 35) trở lên không thể thay đổi trạng thái hoặc chính sách chung của chế độ Không làm phiền (DND) trên thiết bị nữa (bằng cách sửa đổi chế độ cài đặt của người dùng hoặc tắt chế độ DND). Thay vào đó, ứng dụng phải đóng góp một AutomaticZenRule
. Hệ thống sẽ kết hợp chính sách này vào một chính sách chung với lược đồ hiện có là chính sách hạn chế nhất sẽ thắng. Các lệnh gọi đến các API hiện có từng ảnh hưởng đến trạng thái toàn cục (setInterruptionFilter
, setNotificationPolicy
) sẽ dẫn đến việc tạo hoặc cập nhật một AutomaticZenRule
ngầm ẩn. Lệnh gọi này được bật và tắt tuỳ thuộc vào chu kỳ gọi của các lệnh gọi API đó.
Xin lưu ý rằng thay đổi này chỉ ảnh hưởng đến hành vi có thể quan sát được nếu ứng dụng đang gọi setInterruptionFilter(INTERRUPTION_FILTER_ALL)
và dự kiến lệnh gọi đó sẽ huỷ kích hoạt AutomaticZenRule
mà chủ sở hữu của ứng dụng đã kích hoạt trước đó.
Các thay đổi về API của OpenJDK
Android 15 tiếp tục công cuộc làm mới các thư viện cốt lõi của Android để phù hợp với các tính năng trong bản phát hành LTS OpenJDK mới nhất.
Một số thay đổi sau đây có thể ảnh hưởng đến khả năng tương thích của ứng dụng đối với những ứng dụng nhắm đến Android 15 (API cấp 35):
Thay đổi đối với các API định dạng chuỗi: Giờ đây, việc xác thực chỉ mục đối số, cờ, chiều rộng và độ chính xác sẽ nghiêm ngặt hơn khi bạn dùng các API
String.format()
vàFormatter.format()
sau đây:String.format(String, Object[])
String.format(Locale, String, Object[])
Formatter.format(String, Object[])
Formatter.format(Locale, String, Object[])
Ví dụ: ngoại lệ sau sẽ được gửi khi chỉ mục đối số là 0 (
%0
trong chuỗi định dạng):IllegalFormatArgumentIndexException: Illegal format argument index = 0
Trong trường hợp này, bạn có thể khắc phục vấn đề bằng cách sử dụng chỉ mục đối số là 1 (
%1
trong chuỗi định dạng).Thay đổi đối với loại thành phần của
Arrays.asList(...).toArray()
: Khi sử dụngArrays.asList(...).toArray()
, loại thành phần của mảng kết quả hiện làObject
, chứ không phải loại của các phần tử trong mảng cơ bản. Vì vậy, mã sau đây sẽ gửi mộtClassCastException
:String[] elements = (String[]) Arrays.asList("one", "two").toArray();
Trong trường hợp này, để giữ
String
làm loại thành phần trong mảng kết quả, bạn có thể sử dụngCollection.toArray(Object[])
:String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
Các thay đổi đối với việc xử lý mã ngôn ngữ: Khi sử dụng API
Locale
, mã ngôn ngữ cho tiếng Do Thái, tiếng Yiddish và tiếng Indonesia sẽ không còn được chuyển đổi sang các dạng thức cũ (tiếng Do Thái:iw
, tiếng Yiddish:ji
và tiếng Indonesia:in
). Khi chỉ định mã ngôn ngữ cho một trong các ngôn ngữ này, hãy sử dụng mã theo tiêu chuẩn ISO 639-1 (tiếng Do Thái:he
, tiếng Yiddish:yi
và tiếng Indonesia:id
).Các thay đổi đối với chuỗi số nguyên ngẫu nhiên: Sau các thay đổi được thực hiện trong https://bugs.openjdk.org/browse/JDK-8301574, các phương thức
Random.ints()
sau đây hiện trả về một chuỗi số khác với các phương thứcRandom.nextInt()
:Nhìn chung, thay đổi này sẽ không dẫn đến hành vi làm hỏng ứng dụng, nhưng mã của bạn không được mong đợi trình tự được tạo từ các phương thức
Random.ints()
khớp vớiRandom.nextInt()
.
API SequencedCollection
mới có thể ảnh hưởng đến khả năng tương thích của ứng dụng sau khi bạn cập nhật compileSdk
trong cấu hình bản dựng của ứng dụng để sử dụng Android 15 (API cấp 35):
Xung đột với các hàm mở rộng
MutableList.removeFirst()
vàMutableList.removeLast()
trongkotlin-stdlib
Loại
List
trong Java được ánh xạ đến loạiMutableList
trong Kotlin. Vì các APIList.removeFirst()
vàList.removeLast()
đã được ra mắt trong Android 15 (API cấp 35), nên trình biên dịch Kotlin sẽ giải quyết các lệnh gọi hàm (ví dụ:list.removeFirst()
) một cách tĩnh đến các APIList
mới thay vì đến các hàm mở rộng trongkotlin-stdlib
.Nếu một ứng dụng được biên dịch lại với
compileSdk
được đặt thành35
vàminSdk
được đặt thành34
trở xuống, rồi ứng dụng đó chạy trên Android 14 trở xuống, thì sẽ xảy ra lỗi thời gian chạy:java.lang.NoSuchMethodError: No virtual method removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
Lựa chọn
NewApi
lint hiện có trong Trình bổ trợ Android cho Gradle có thể phát hiện những cách sử dụng API mới này../gradlew lint
MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi] list.removeFirst()Để khắc phục ngoại lệ thời gian chạy và lỗi lint, bạn có thể thay thế các lệnh gọi hàm
removeFirst()
vàremoveLast()
bằngremoveAt(0)
vàremoveAt(list.lastIndex)
tương ứng trong Kotlin. Nếu bạn đang sử dụng Android Studio Ladybug | 2024.1.3 trở lên, thì phiên bản này cũng cung cấp lựa chọn sửa nhanh cho những lỗi này.Hãy cân nhắc việc xoá
@SuppressLint("NewApi")
vàlintOptions { disable 'NewApi' }
nếu bạn đã tắt lựa chọn lint.Xung đột với các phương thức khác trong Java
Các phương thức mới đã được thêm vào các loại hiện có, ví dụ:
List
vàDeque
. Những phương thức mới này có thể không tương thích với các phương thức có cùng tên và kiểu đối số trong các giao diện và lớp khác. Trong trường hợp xảy ra xung đột chữ ký phương thức với sự không tương thích, trình biên dịchjavac
sẽ xuất ra lỗi thời gian tạo. Ví dụ:Ví dụ về lỗi 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 ListVí dụ về lỗi 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 errorVí dụ về lỗi 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Để khắc phục những lỗi này khi tạo bản dựng, lớp triển khai các giao diện này phải ghi đè phương thức bằng một kiểu dữ liệu trả về tương thích. Ví dụ:
@Override public Object getFirst() { return List.super.getFirst(); }
Bảo mật
Android 15 có những thay đổi giúp tăng cường tính bảo mật của hệ thống để bảo vệ ứng dụng và người dùng khỏi các ứng dụng độc hại.
Các phiên bản TLS bị hạn chế
Android 15 hạn chế việc sử dụng TLS phiên bản 1.0 và 1.1. Các phiên bản này trước đây đã ngừng hoạt động trong Android, nhưng hiện không được phép sử dụng cho các ứng dụng nhắm đến Android 15.
Khởi chạy hoạt động trong nền một cách an toàn
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 aPendingIntent
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.
Ý định an toàn hơn
Android 15 ra mắt các biện pháp bảo mật mới (không bắt buộc) để giúp ý định trở nên an toàn hơn và mạnh mẽ hơn. Những thay đổi này nhằm ngăn chặn các lỗ hổng tiềm ẩn và việc sử dụng sai ý định mà các ứng dụng độc hại có thể khai thác. Có hai điểm cải tiến chính về bảo mật của ý định trong Android 15:
- So khớp bộ lọc ý định mục tiêu: Các ý định nhắm mục tiêu các thành phần cụ thể phải khớp chính xác với thông số kỹ thuật của bộ lọc ý định của mục tiêu. Nếu bạn gửi một ý định để khởi chạy hoạt động của một ứng dụng khác, thì thành phần ý định mục tiêu cần phải phù hợp với bộ lọc ý định đã khai báo của hoạt động nhận.
- Ý định phải có hành động: Ý định không có hành động sẽ không còn khớp với bất kỳ bộ lọc ý định nào. Tức là các ý định dùng để bắt đầu hoạt động hoặc phải có hành động được xác định rõ ràng.
Để kiểm tra cách ứng dụng của bạn phản hồi những thay đổi này, hãy sử dụng StrictMode
trong ứng dụng. Để xem nhật ký chi tiết về các lỗi vi phạm việc sử dụng Intent
, hãy thêm phương thức sau:
Kotlin
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() .detectUnsafeIntentLaunch() .build() ) }
Java
public void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() .detectUnsafeIntentLaunch() .build()); }
Trải nghiệm người dùng và giao diện người dùng hệ thống
Android 15 có một số thay đổi nhằm mang đến trải nghiệm người dùng nhất quán và trực quan hơn.
Thay đổi phần lồng ghép cửa sổ
Android 15 中与窗口内边距相关的两项变更:默认强制执行边到边,此外还有配置变更,例如系统栏的默认配置。
Thực thi chi tiết
Theo mặc định, các ứng dụng sẽ hiển thị tràn viền trên các thiết bị chạy Android 15 nếu ứng dụng đó nhắm đến Android 15 (API cấp 35).

Đây là một thay đổi có thể gây ảnh hưởng tiêu cực đến giao diện người dùng của ứng dụng. Những thay đổi này ảnh hưởng đến các khu vực sau trên giao diện người dùng:
- Thanh điều hướng bằng cử chỉ
- Trong suốt theo mặc định.
- Độ lệch dưới cùng bị vô hiệu hoá nên nội dung nằm phía sau thanh điều hướng của hệ thống, trừ phi bạn áp dụng phần lồng ghép.
setNavigationBarColor
vàR.attr#navigationBarColor
đã ngừng hoạt động và không ảnh hưởng đến chế độ thao tác bằng cử chỉ.setNavigationBarContrastEnforced
vàR.attr#navigationBarContrastEnforced
vẫn không ảnh hưởng đến chế độ thao tác bằng cử chỉ.
- Thao tác bằng 3 nút
- Độ mờ được đặt thành 80% theo mặc định, có thể có màu trùng với nền cửa sổ.
- Đã tắt độ lệch dưới cùng để nội dung nằm phía sau thanh điều hướng của hệ thống, trừ phi bạn áp dụng phần lồng ghép.
setNavigationBarColor
vàR.attr#navigationBarColor
được đặt để khớp với nền cửa sổ theo mặc định. Nền cửa sổ phải là một đối tượng có thể vẽ màu để áp dụng chế độ mặc định này. API này không được dùng nữa nhưng vẫn ảnh hưởng đến chế độ thao tác bằng 3 nút.setNavigationBarContrastEnforced
vàR.attr#navigationBarContrastEnforced
theo mặc định là true, thêm nền không trong suốt 80% trên chế độ thao tác bằng 3 nút.
- Thanh trạng thái
- Trong suốt theo mặc định.
- Độ lệch trên cùng bị vô hiệu hoá nên nội dung nằm phía sau thanh trạng thái, trừ phi bạn áp dụng phần lồng ghép.
setStatusBarColor
vàR.attr#statusBarColor
không được dùng nữa và không có hiệu lực trên Android 15.setStatusBarContrastEnforced
vàR.attr#statusBarContrastEnforced
không còn được dùng nữa nhưng vẫn có ảnh hưởng đến Android 15.
- Vết cắt trên màn hình
layoutInDisplayCutoutMode
của các cửa sổ không nổi phải làLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
.SHORT_EDGES
,NEVER
vàDEFAULT
được diễn giải làALWAYS
để người dùng không thấy thanh màu đen do vết cắt trên màn hình và xuất hiện tràn viền.
Ví dụ sau đây cho thấy một ứng dụng trước và sau khi nhắm đến Android 15 (API cấp 35), cũng như trước và sau khi áp dụng phần lồng ghép. Ví dụ này chưa đầy đủ và có thể xuất hiện khác trên Android Auto.



Những điều cần kiểm tra nếu ứng dụng của bạn đã hiển thị tràn viền
Nếu ứng dụng của bạn đã hiển thị tràn viền và áp dụng phần lồng ghép, thì hầu hết bạn sẽ không bị ảnh hưởng, ngoại trừ trong các trường hợp sau. Tuy nhiên, ngay cả khi cho rằng ứng dụng của mình không bị ảnh hưởng, bạn vẫn nên kiểm thử ứng dụng.
- Bạn có một cửa sổ không nổi, chẳng hạn như
Activity
sử dụngSHORT_EDGES
,NEVER
hoặcDEFAULT
thay vìLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
. Nếu ứng dụng của bạn gặp sự cố khi khởi chạy, thì có thể là do màn hình chờ. Bạn có thể nâng cấp phần phụ thuộc core splashscreen lên 1.2.0-alpha01 trở lên hoặc đặtwindow.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always
. - Có thể có những màn hình có lưu lượng truy cập thấp hơn với giao diện người dùng bị che khuất. Xác minh rằng những màn hình ít được truy cập này không có giao diện người dùng bị che khuất. Các màn hình có lưu lượng truy cập thấp bao gồm:
- Màn hình hướng dẫn bắt đầu dùng ứng dụng hoặc màn hình đăng nhập
- Trang cài đặt
Những điều cần kiểm tra nếu ứng dụng của bạn chưa hiển thị tràn viền
Nếu ứng dụng của bạn chưa hiển thị tràn viền, thì rất có thể bạn sẽ bị ảnh hưởng. Ngoài các trường hợp dành cho những ứng dụng đã hiển thị tràn viền, bạn nên cân nhắc những trường hợp sau:
- Nếu ứng dụng của bạn dùng các thành phần Material 3 (
androidx.compose.material3
) trong Compose, chẳng hạn nhưTopAppBar
,BottomAppBar
vàNavigationBar
, thì những thành phần này có thể không bị ảnh hưởng vì chúng tự động xử lý phần lồng ghép. - Nếu ứng dụng của bạn đang dùng các Thành phần Material 2 (
androidx.compose.material
) trong Compose, thì các thành phần này sẽ không tự động xử lý phần lồng ghép. Tuy nhiên, bạn có thể truy cập vào những phần lồng ghép này và áp dụng chúng theo cách thủ công. Trong androidx.compose.material 1.6.0 trở lên, hãy dùng tham sốwindowInsets
để áp dụng phần lồng ghép theo cách thủ công choBottomAppBar
,TopAppBar
,BottomNavigation
vàNavigationRail
. Tương tự, hãy dùng tham sốcontentWindowInsets
choScaffold
. - Nếu ứng dụng của bạn dùng các khung hiển thị và Thành phần Material (
com.google.android.material
), thì hầu hết Thành phần Material dựa trên khung hiển thị (chẳng hạn nhưBottomNavigationView
,BottomAppBar
,NavigationRailView
hoặcNavigationView
) sẽ xử lý phần lồng ghép và không yêu cầu bạn làm gì thêm. Tuy nhiên, bạn cần thêmandroid:fitsSystemWindows="true"
nếu dùngAppBarLayout
. - Đối với các thành phần kết hợp tuỳ chỉnh, hãy áp dụng phần lồng ghép theo cách thủ công dưới dạng khoảng đệm. Nếu nội dung của bạn nằm trong
Scaffold
, bạn có thể sử dụng phần lồng ghép bằng cách dùng các giá trị khoảng đệmScaffold
. Nếu không, hãy áp dụng khoảng đệm bằng một trong cácWindowInsets
. - Nếu ứng dụng của bạn đang dùng khung hiển thị và
BottomSheet
,SideSheet
hoặc các vùng chứa tuỳ chỉnh, hãy áp dụng khoảng đệm bằngViewCompat.setOnApplyWindowInsetsListener
. Đối vớiRecyclerView
, hãy áp dụng khoảng đệm bằng trình nghe này, đồng thời thêmclipToPadding="false"
.
Những điều cần kiểm tra nếu ứng dụng của bạn phải cung cấp tính năng bảo vệ tuỳ chỉnh ở chế độ nền
Nếu ứng dụng của bạn phải cung cấp chế độ bảo vệ tuỳ chỉnh ở chế độ nền cho chế độ thao tác bằng 3 nút hoặc thanh trạng thái, thì ứng dụng của bạn nên đặt một thành phần kết hợp hoặc khung hiển thị phía sau thanh hệ thống bằng cách sử dụng WindowInsets.Type#tappableElement()
để lấy chiều cao thanh điều hướng bằng 3 nút hoặc WindowInsets.Type#statusBars
.
Tài nguyên bổ sung về chế độ hiển thị tràn viền
Hãy xem hướng dẫn về Chế độ xem tràn viền và Compose tràn viền để biết thêm các điểm cần cân nhắc khi áp dụng phần lồng ghép.
API không dùng nữa
Các API sau đây không còn được dùng nữa nhưng chưa bị vô hiệu hoá:
R.attr#enforceStatusBarContrast
R.attr#navigationBarColor
(đối với chế độ thao tác bằng 3 nút, với 80% alpha)Window#isStatusBarContrastEnforced
Window#setNavigationBarColor
(đối với chế độ thao tác bằng 3 nút, với 80% alpha)Window#setStatusBarContrastEnforced
Các API sau đây không được dùng nữa và bị vô hiệu hoá:
R.attr#navigationBarColor
(đối với chế độ thao tác bằng cử chỉ)R.attr#navigationBarDividerColor
R.attr#statusBarColor
Window#setDecorFitsSystemWindows
Window#getNavigationBarColor
Window#getNavigationBarDividerColor
Window#getStatusBarColor
Window#setNavigationBarColor
(đối với chế độ thao tác bằng cử chỉ)Window#setNavigationBarDividerColor
Window#setStatusBarColor
Cấu hình ổn định
如果您的应用以 Android 15(API 级别 35)或更高版本为目标平台,Configuration
不再排除系统栏。如果您在 Configuration
类中使用屏幕尺寸进行布局计算,则应根据需要将其替换为更好的替代方案,例如适当的 ViewGroup
、WindowInsets
或 WindowMetricsCalculator
。
Configuration
自 API 1 起便已开始提供。它通常从 Activity.onConfigurationChanged
中获取。它提供窗口密度、方向和大小等信息。从 Configuration
返回的窗口大小的一个重要特征是,它之前排除了系统栏。
配置大小通常用于资源选择,例如 /res/layout-h500dp
,这仍然是一个有效的使用情形。不过,我们一直不建议使用它进行布局计算。如果您正在这样做,请立即远离该设备。您应根据自己的使用场景,将 Configuration
的使用替换为更合适的用法。
如果您使用它来计算布局,请使用适当的 ViewGroup
,例如 CoordinatorLayout
或 ConstraintLayout
。如果您使用它来确定系统导航栏的高度,请使用 WindowInsets
。如果您想知道应用窗口的当前大小,请使用 computeCurrentWindowMetrics
。
以下列表介绍了受此变更影响的字段:
Configuration.screenWidthDp
和screenHeightDp
尺寸不再排除系统栏。Configuration.smallestScreenWidthDp
会受到screenWidthDp
和screenHeightDp
更改的间接影响。Configuration.orientation
会受到近乎正方形的设备上screenWidthDp
和screenHeightDp
更改的间接影响。Display.getSize(Point)
间接受到Configuration
中的更改影响。此方法已从 API 级别 30 开始弃用。- 自 API 级别 33 以来,
Display.getMetrics()
一直以这种方式运行。
Thuộc tính elegantTextHeight mặc định là true
Đối với các ứng dụng nhắm đến Android 15 (API cấp 35), thuộc tính elegantTextHeight
TextView
sẽ trở thành true
theo mặc định, thay thế phông chữ thu gọn được sử dụng theo mặc định bằng một số tập lệnh có các chỉ số dọc lớn bằng một tập lệnh dễ đọc hơn nhiều.
Phông chữ nhỏ gọn được giới thiệu để ngăn các bố cục bị phá vỡ; Android 13 (API cấp 33) ngăn chặn nhiều sự cố này bằng cách cho phép bố cục văn bản kéo giãn chiều cao theo chiều dọc bằng cách sử dụng thuộc tính fallbackLineSpacing
.
Trong Android 15, phông chữ thu gọn vẫn còn trong hệ thống, vì vậy, ứng dụng của bạn có thể đặt elegantTextHeight
thành false
để có cùng hành vi như trước, nhưng có thể sẽ không được hỗ trợ trong các bản phát hành sắp tới. Vì vậy, nếu ứng dụng của bạn hỗ trợ các tập lệnh sau: tiếng Ả Rập, tiếng Lào, tiếng Myanmar, tiếng Tamil, tiếng Gujarati, tiếng Kannada, tiếng Malayalam, tiếng Odia, tiếng Telugu hoặc tiếng Thái, hãy kiểm thử ứng dụng bằng cách đặt elegantTextHeight
thành true
.
elegantTextHeight
của 

elegantTextHeight
hành vi cho các ứng dụng nhắm đến Android 15.Chiều rộng TextView thay đổi đối với các hình dạng chữ cái phức tạp
In previous versions of Android, some cursive fonts or languages that have
complex shaping might draw the letters in the previous or next character's area.
In some cases, such letters were clipped at the beginning or ending position.
Starting in Android 15, a TextView
allocates width for drawing enough space
for such letters and allows apps to request extra paddings to the left to
prevent clipping.
Because this change affects how a TextView
decides the width, TextView
allocates more width by default if the app targets Android 15 (API level 35) or
higher. You can enable or disable this behavior by calling the
setUseBoundsForWidth
API on TextView
.
Because adding left padding might cause a misalignment for existing layouts, the
padding is not added by default even for apps that target Android 15 or higher.
However, you can add extra padding to preventing clipping by calling
setShiftDrawingOffsetForStartOverhang
.
The following examples show how these changes can improve text layout for some fonts and languages.

<TextView android:fontFamily="cursive" android:text="java" />

<TextView android:fontFamily="cursive" android:text="java" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />

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

<TextView android:text="คอมพิวเตอร์" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />
Chiều cao dòng mặc định theo ngôn ngữ cho EditText
Trong các phiên bản Android trước, bố cục văn bản đã kéo giãn chiều cao của văn bản để đáp ứng chiều cao dòng của phông chữ khớp với ngôn ngữ hiện tại. Ví dụ: nếu nội dung bằng tiếng Nhật, thì chiều cao dòng của phông chữ tiếng Nhật sẽ lớn hơn một chút so với chiều cao dòng của phông chữ Latinh, do đó chiều cao của văn bản sẽ lớn hơn một chút. Tuy nhiên, mặc dù có sự khác biệt về chiều cao dòng, nhưng phần tử EditText
được định cỡ đồng nhất, bất kể ngôn ngữ đang được sử dụng, như minh hoạ trong hình sau:

EditText
có thể chứa văn bản bằng tiếng Anh (en), tiếng Nhật (ja) và tiếng Miến Điện (my). Chiều cao của EditText
là như nhau, mặc dù các ngôn ngữ này có chiều cao dòng khác nhau.Đối với các ứng dụng nhắm đến Android 15 (API cấp 35), chiều cao dòng tối thiểu hiện được dành riêng cho EditText
để khớp với phông chữ tham chiếu cho Ngôn ngữ được chỉ định, như minh hoạ trong hình sau:

EditText
có thể chứa văn bản bằng tiếng Anh (en), tiếng Nhật (ja) và tiếng Miến Điện (my). Chiều cao của EditText
hiện bao gồm khoảng trống để phù hợp với chiều cao dòng mặc định cho phông chữ của các ngôn ngữ này.Nếu cần, ứng dụng của bạn có thể khôi phục hành vi trước đó bằng cách chỉ định thuộc tính useLocalePreferredLineHeightForMinimum
thành false
và ứng dụng có thể đặt các chỉ số dọc tối thiểu tuỳ chỉnh bằng API setMinimumFontMetrics
trong Kotlin và Java.
Camera và nội dung nghe nhìn
Android 15 thực hiện những thay đổi sau đối với hành vi của camera và nội dung nghe nhìn cho các ứng dụng nhắm đến Android 15 trở lên.
Quy định hạn chế đối với việc yêu cầu quyền phát âm thanh
以 Android 15(API 级别 35)为目标平台的应用必须是顶部应用或正在运行前台服务,才能请求音频焦点。如果应用在未满足上述任一要求的情况下尝试请求焦点,调用将返回 AUDIOFOCUS_REQUEST_FAILED
。
如需详细了解音频焦点,请参阅管理音频焦点。
Các quy tắc hạn chế mới cập nhật đối với yếu tố ngoài SDK
Android 15 包含更新后的受限非 SDK 接口列表(基于与 Android 开发者之间的协作以及最新的内部测试)。在限制使用非 SDK 接口之前,我们会尽可能确保有可用的公开替代方案。
如果您的应用并非以 Android 15 为目标平台,其中一些变更可能不会立即对您产生影响。不过,虽然您的应用可以访问某些非 SDK 接口(具体取决于应用的目标 API 级别),但只要您使用任何非 SDK 方法或字段,终归存在导致应用出问题的显著风险。
如果您不确定自己的应用是否使用了非 SDK 接口,则可以测试该应用,进行确认。如果您的应用依赖于非 SDK 接口,则应该开始计划迁移到 SDK 替代方案。不过,我们知道某些应用具有使用非 SDK 接口的有效用例。如果您无法为应用中的某项功能找到使用非 SDK 接口的替代方案,则应该请求新的公共 API。
如需详细了解此 Android 版本中的变更,请参阅 Android 15 中有关限制非 SDK 接口的更新。如需全面了解有关非 SDK 接口的详细信息,请参阅对非 SDK 接口的限制。