Thay đổi về hành vi: ứng dụng nhắm đến API cấp 28 trở lên

Android 9 (API cấp 28) giới thiệu một số thay đổi đối với hệ thống Android. Những thay đổi sau đây về hành vi chỉ áp dụng cho ứng dụng nhắm đến API cấp 28 trở lên. Các ứng dụng đặt targetSdkVersion thành API cấp 28 trở lên phải sửa đổi để hỗ trợ những hành vi này cho phù hợp (nếu phù hợp).

Đối với các thay đổi ảnh hưởng đến tất cả các ứng dụng chạy trên Android 9, bất kể các thay đổi đó nhắm đến cấp độ API nào, hãy xem phần Thay đổi về hành vi: tất cả ứng dụng.

Dịch vụ trên nền trước

Các ứng dụng nhắm đến Android 9 trở lên và sử dụng dịch vụ trên nền trước phải yêu cầu quyền FOREGROUND_SERVICE. Đây là một quyền thông thường, do đó, hệ thống sẽ tự động cấp quyền đó cho ứng dụng yêu cầu.

Nếu một ứng dụng nhắm đến Android 9 trở lên cố gắng tạo dịch vụ trên nền trước mà không yêu cầu FOREGROUND_SERVICE, thì hệ thống sẽ gửi ra một SecurityException.

Các thay đổi về quyền riêng tư

Nếu ứng dụng của bạn nhắm đến Android 9, bạn nên lưu ý những thay đổi sau đây về hành vi. Những bản cập nhật này đối với thông tin về DNS và sê-ri của thiết bị sẽ giúp tăng cường quyền riêng tư của người dùng.

Ngừng sử dụng số sê-ri của bản dựng

Trong Android 9, Build.SERIAL luôn được đặt thành "UNKNOWN" để bảo vệ quyền riêng tư của người dùng.

Nếu ứng dụng của bạn cần truy cập vào số sê-ri phần cứng của thiết bị, thì bạn nên yêu cầu quyền READ_PHONE_STATE, sau đó gọi getSerial().

Bảo mật DNS

Ứng dụng nhắm đến Android 9 phải tuân thủ các API DNS riêng. Cụ thể, các ứng dụng phải đảm bảo rằng nếu trình phân giải hệ thống đang thực hiện DNS qua TLS, thì mọi ứng dụng DNS tích hợp đều sử dụng DNS đã mã hoá cho cùng một tên máy chủ với hệ thống hoặc bị tắt và thay vào đó là trình phân giải hệ thống.

Các thay đổi về tính bảo mật của khung

Android 9 có một số thay đổi về hành vi giúp cải thiện tính bảo mật của ứng dụng, nhưng những thay đổi này chỉ có hiệu lực nếu ứng dụng của bạn nhắm đến API cấp 28 trở lên.

TLS mạng được bật theo mặc định

Nếu ứng dụng của bạn nhắm đến Android 9 trở lên, thì phương thức isCleartextTrafficPermitted() sẽ trả về false theo mặc định. Nếu ứng dụng của bạn cần bật văn bản thô cho các miền cụ thể, thì bạn phải đặt cleartextTrafficPermitted thành true một cách rõ ràng cho các miền đó trong Cấu hình bảo mật mạng của ứng dụng.

Thư mục dữ liệu dựa trên web được phân tách theo quy trình

Để cải thiện độ ổn định và tính toàn vẹn của dữ liệu trong Android 9, các ứng dụng không thể dùng chung một thư mục dữ liệu WebView trong nhiều quy trình. Thông thường, các thư mục dữ liệu như vậy sẽ lưu trữ cookie, bộ nhớ đệm HTTP cũng như các bộ nhớ tạm thời và ổn định khác liên quan đến hoạt động duyệt web.

Trong hầu hết trường hợp, ứng dụng chỉ nên dùng các lớp trong gói android.webkit, chẳng hạn như WebViewCookieManager, chỉ trong một quy trình. Ví dụ: bạn nên di chuyển tất cả các đối tượng Activity sử dụng WebView vào cùng một quy trình. Bạn có thể thực thi nghiêm ngặt hơn quy tắc "chỉ một quy trình" bằng cách gọi disableWebView() trong các quy trình khác của ứng dụng. Lệnh gọi này ngăn không cho WebView khởi chạy trong các quy trình khác đó do nhầm lẫn, ngay cả khi mã đó được gọi từ một thư viện phụ thuộc.

Nếu ứng dụng của bạn phải sử dụng các thực thể của WebView trong nhiều quy trình, thì bạn phải chỉ định một hậu tố thư mục dữ liệu duy nhất cho từng quy trình bằng phương thức WebView.setDataDirectorySuffix() trước khi sử dụng một thực thể cụ thể của WebView trong quy trình đó. Phương thức này đặt dữ liệu web của mỗi quy trình vào thư mục riêng thuộc thư mục dữ liệu của ứng dụng.

Miền SELinux cho mỗi ứng dụng

Ứng dụng nhắm đến Android 9 trở lên không thể chia sẻ dữ liệu với các ứng dụng khác bằng cách dùng các quyền Unix mà mọi người có thể truy cập. Thay đổi này giúp cải thiện tính toàn vẹn của Hộp cát ứng dụng Android, đặc biệt là yêu cầu về việc chỉ có ứng dụng đó mới truy cập được dữ liệu riêng tư của một ứng dụng.

Để chia sẻ tệp với các ứng dụng khác, hãy dùng trình cung cấp nội dung.

Các thay đổi về khả năng kết nối

Đếm dữ liệu kết nối và đa đường dẫn

Trong các ứng dụng nhắm đến Android 9 trở lên, hệ thống sẽ tính lưu lượng truy cập mạng trên các mạng không phải chế độ mặc định hiện tại (chẳng hạn như lưu lượng truy cập di động khi thiết bị đang dùng Wi-Fi), đồng thời cung cấp các phương thức trong lớp NetworkStatsManager để truy vấn lưu lượng truy cập đó.

Cụ thể, getMultipathPreference() hiện sẽ trả về một giá trị dựa trên lưu lượng truy cập mạng nêu trên. Kể từ Android 9, phương thức này sẽ trả về true cho dữ liệu ô. Tuy nhiên, khi tích luỹ nhiều hơn một mức lưu lượng truy cập nhất định trong một ngày, phương thức này sẽ bắt đầu trả về false. Các ứng dụng chạy trên Android 9 phải gọi phương thức này và tuân theo gợi ý này.

Lớp ConnectivityManager.NetworkCallback hiện sẽ gửi thông tin về VPN đến các ứng dụng. Thay đổi này giúp các ứng dụng theo dõi các sự kiện kết nối dễ dàng hơn mà không cần kết hợp các lệnh gọi đồng bộ và không đồng bộ cũng như sử dụng các API bị hạn chế. Ngoài ra, điều này có nghĩa là tính năng chuyển thông tin hoạt động như dự kiến khi một thiết bị được kết nối đồng thời với nhiều mạng Wi-Fi hoặc nhiều mạng di động.

Ngừng sử dụng ứng dụng HTTP HTTP

Với Android 6.0, chúng tôi đã ngừng hỗ trợ ứng dụng HTTP HTTP. Kể từ Android 9, thư viện đó sẽ bị xoá khỏi đường dẫn lớp khởi động và không có sẵn cho các ứng dụng theo mặc định.

Để tiếp tục sử dụng ứng dụng Apache HTTP, các ứng dụng nhắm đến Android 9 trở lên có thể thêm đoạn mã sau vào AndroidManifest.xml:

<uses-library android:name="org.apache.http.legacy" android:required="false"/>

Thay vì sử dụng thư viện Apache thời gian chạy, các ứng dụng có thể gói phiên bản thư viện org.apache.http riêng trong tệp APK. Nếu làm như vậy, bạn phải đóng gói lại thư viện (bằng một tiện ích như Jar Jar) để tránh các vấn đề về khả năng tương thích của lớp với các lớp được cung cấp trong thời gian chạy.

Các thay đổi về giao diện người dùng

Xem tiêu điểm

Bạn không thể lấy tiêu điểm cho các chế độ xem có khu vực bằng 0 (chiều rộng hoặc chiều cao là 0).

Ngoài ra, các hoạt động không còn ngầm gán tiêu điểm ban đầu ở chế độ cảm ứng. Thay vào đó, bạn có thể yêu cầu rõ ràng tiêu điểm ban đầu nếu muốn.

Xử lý giá trị hex CSS RGBA

Các ứng dụng nhắm mục tiêu Android 9 trở lên phải bật hành vi nháp Mô-đun màu CSS cấp 4 để xử lý các màu CSS 4 và 8 chữ số hex.

Mô-đun màu CSS cấp 4 đã được Chrome hỗ trợ kể từ bản phát hành 52, nhưng WebView hiện vô hiệu hóa tính năng này vì phát hiện thấy các ứng dụng Android hiện có chứa màu hex 32 bit theo thứ tự Android (ARGB), điều này sẽ gây ra lỗi kết xuất.

Ví dụ: màu #80ff8080 hiện hiển thị trong WebView dưới dạng màu đỏ nhạt (#ff8080) đối với ứng dụng nhắm mục tiêu API cấp 27 trở xuống. Thành phần chính (mà Android sẽ diễn giải là thành phần alpha) hiện bị bỏ qua. Nếu một ứng dụng nhắm đến API cấp 28 trở lên, thì #80ff8080 sẽ được hiểu là 50% màu xanh lục nhạt trong suốt (#80ff80).

Phân tích loại MIME cho tệp: URI

Các phiên bản Android trước Android 9 có thể suy ra loại MIME từ nội dung tệp. Kể từ Android 9 (API cấp 28), các ứng dụng phải sử dụng đúng đuôi tệp khi tải URI file: trong WebView.

Việc sử dụng nội dung tệp để suy luận loại MIME có thể là một nguồn gây ra lỗi bảo mật và điều này thường không được các trình duyệt hiện đại cho phép.

Nếu một tệp có đuôi tệp được nhận dạng như .html, .txt, .js hoặc .css, thì loại MIME sẽ được xác định theo đuôi tệp. Nếu một tệp không có đuôi hoặc không nhận dạng được tệp, thì loại MIME sẽ là văn bản thuần tuý.

Ví dụ: một URI như file:///sdcard/test.html sẽ được kết xuất dưới dạng HTML, nhưng một URI như file:///sdcard/test sẽ hiển thị dưới dạng văn bản thuần tuý, ngay cả khi tệp chứa dữ liệu HTML.

Phần tử cuộn tài liệu

Android 9 xử lý đúng cách trường hợp phần tử gốc của tài liệu là phần tử cuộn. Trong các phiên bản trước, vị trí cuộn được đặt cho phần tử nội dung còn phần tử gốc không có giá trị cuộn. Android 9 kích hoạt hành vi tuân thủ tiêu chuẩn, trong đó phần tử cuộn phần tử gốc.

Ngoài ra, việc truy cập trực tiếp vào document.body.scrollTop, document.body.scrollLeft, document.documentElement.scrollTop hoặc document.documentElement.scrollLeft sẽ hoạt động khác nhau tuỳ thuộc vào SDK mục tiêu. Để truy cập vào các giá trị cuộn trong khung nhìn, hãy sử dụng document.scrollingElement nếu có.

Thông báo của các ứng dụng bị tạm ngưng

Trước Android 9, thông báo của các ứng dụng bị tạm ngưng đều bị huỷ. Kể từ Android 9, thông báo của các ứng dụng bị tạm ngưng sẽ bị ẩn cho đến khi ứng dụng đó tiếp tục hoạt động.