Android 17 mang đến cho nhà phát triển các tính năng và API mới tuyệt vời. Các phần sau đây tóm tắt những tính năng này để giúp bạn làm quen với các API liên quan.
Để biết danh sách chi tiết về các API mới, đã được sửa đổi, cũng như đã bị xoá, hãy đọc báo cáo điểm khác biệt về API. Để biết thông tin chi tiết về các API mới, hãy truy cập vào tài liệu tham khảo về API cho Android (các API mới được trình bày nổi bật).
Bạn cũng nên xem xét những khía cạnh mà các thay đổi của nền tảng có thể ảnh hưởng đến ứng dụng của bạn. Để biết thêm thông tin, hãy xem các trang sau:
- Các thay đổi về hành vi ảnh hưởng đến ứng dụng khi ứng dụng nhắm đến Android 17
- Các thay đổi về hành vi ảnh hưởng đến tất cả ứng dụng bất kể
targetSdkVersion.
Chức năng cốt lõi
Android 17 bổ sung các tính năng mới sau đây liên quan đến chức năng cốt lõi của Android.
Điều kiện kích hoạt ProfilingManager mới
Android 17 bổ sung một số điều kiện kích hoạt hệ thống mới cho ProfilingManager để giúp bạn thu thập dữ liệu chuyên sâu nhằm gỡ lỗi hiệu suất.
Các điều kiện kích hoạt mới là:
TRIGGER_TYPE_COLD_START: Sự kiện kích hoạt xảy ra trong quá trình khởi động nguội ứng dụng. Thao tác này cung cấp cả mẫu ngăn xếp lệnh gọi và dấu vết hệ thống trong phản hồi.TRIGGER_TYPE_OOM: Sự kiện kích hoạt xảy ra khi một ứng dụng gửiOutOfMemoryErrorvà cung cấp một Java Heap Dump để phản hồi.TRIGGER_TYPE_KILL_EXCESSIVE_CPU_USAGE: Sự kiện kích hoạt xảy ra khi một ứng dụng bị tắt do mức sử dụng CPU bất thường và quá mức, đồng thời cung cấp một mẫu ngăn xếp lệnh gọi để phản hồi.
Để tìm hiểu cách thiết lập trình kích hoạt hệ thống, hãy xem tài liệu về phân tích hiệu suất dựa trên trình kích hoạt và cách truy xuất và phân tích dữ liệu phân tích hiệu suất.
API JobDebugInfo
Android 17 ra mắt các API JobDebugInfo mới để giúp nhà phát triển gỡ lỗi các công việc JobScheduler của họ – lý do công việc không chạy, thời gian chạy và các thông tin tổng hợp khác.
Phương thức đầu tiên của JobDebugInfo API mở rộng là getPendingJobReasonStats(), phương thức này trả về một bản đồ gồm các lý do khiến công việc ở trạng thái đang chờ thực thi và thời lượng tích luỹ tương ứng của trạng thái đang chờ. Phương thức này kết hợp các phương thức getPendingJobReasonsHistory() và getPendingJobReasons() để giúp bạn hiểu rõ lý do một công việc đã lên lịch không chạy như mong đợi, nhưng đơn giản hoá việc truy xuất thông tin bằng cách cung cấp cả thời lượng và lý do của công việc trong một phương thức duy nhất.
Ví dụ: đối với một jobId cụ thể, phương thức này có thể trả về PENDING_JOB_REASON_CONSTRAINT_CHARGING và thời lượng là 60000 mili giây, cho biết công việc đang ở trạng thái chờ trong 60000 mili giây do không đáp ứng được hạn chế về việc sạc.
Quyền riêng tư
Android 17 có các tính năng mới sau đây để cải thiện quyền riêng tư của người dùng.
Trình chọn người liên hệ trên Android
Trình chọn danh bạ Android là một giao diện tiêu chuẩn mà người dùng có thể duyệt để chia sẻ danh bạ với ứng dụng của bạn. Trình chọn này có trên các thiết bị chạy Android 17 trở lên và là một giải pháp thay thế giúp bảo vệ quyền riêng tư cho quyền READ_CONTACTS trên diện rộng. Thay vì yêu cầu quyền truy cập vào toàn bộ sổ địa chỉ của người dùng, ứng dụng của bạn sẽ chỉ định các trường dữ liệu mà ứng dụng cần, chẳng hạn như số điện thoại hoặc địa chỉ email, và người dùng sẽ chọn những người liên hệ cụ thể để chia sẻ. Điều này chỉ cấp cho ứng dụng của bạn quyền đọc đối với dữ liệu đã chọn, đảm bảo quyền kiểm soát chi tiết trong khi mang đến trải nghiệm nhất quán cho người dùng với các chức năng tìm kiếm, chuyển đổi hồ sơ và chọn nhiều mục được tích hợp sẵn mà không cần phải tạo hoặc duy trì giao diện người dùng.
Để biết thêm thông tin, hãy xem tài liệu về công cụ chọn người liên hệ.
Bảo mật
Android 17 bổ sung các tính năng mới sau đây để cải thiện tính bảo mật của thiết bị và ứng dụng.
Chế độ Bảo vệ nâng cao trên Android (AAPM)
Chế độ Bảo vệ nâng cao của Android cung cấp cho người dùng Android một bộ tính năng bảo mật mới mạnh mẽ, đánh dấu một bước tiến quan trọng trong việc bảo vệ người dùng (đặc biệt là những người dùng có nguy cơ cao hơn) khỏi các cuộc tấn công tinh vi. Được thiết kế như một tính năng chọn sử dụng, AAPM được kích hoạt bằng một chế độ cài đặt cấu hình duy nhất mà người dùng có thể bật bất cứ lúc nào để áp dụng một bộ biện pháp bảo vệ bảo mật theo ý kiến riêng.
Các cấu hình cốt lõi này bao gồm việc chặn cài đặt ứng dụng từ các nguồn không xác định (tải ứng dụng bên ngoài), hạn chế tín hiệu dữ liệu USB và bắt buộc quét bằng Google Play Protect, giúp giảm đáng kể phạm vi tấn công của thiết bị.
Nhà phát triển có thể tích hợp với tính năng này bằng cách sử dụng API AdvancedProtectionManager để phát hiện trạng thái của chế độ, cho phép các ứng dụng tự động áp dụng trạng thái bảo mật tăng cường hoặc hạn chế chức năng có rủi ro cao khi người dùng đã chọn sử dụng.
Khả năng kết nối
Android 17 bổ sung các tính năng sau để cải thiện khả năng kết nối của thiết bị và ứng dụng.
Mạng vệ tinh bị hạn chế
Triển khai các hoạt động tối ưu hoá để cho phép ứng dụng hoạt động hiệu quả trên các mạng vệ tinh có băng thông thấp.
Trải nghiệm người dùng và giao diện người dùng hệ thống
Android 17 có những thay đổi sau đây để cải thiện trải nghiệm người dùng.
Handoff
Handoff là một tính năng và API mới sắp có trên Android 17. Các nhà phát triển ứng dụng có thể tích hợp tính năng này để mang đến trải nghiệm liền mạch trên nhiều thiết bị cho người dùng. Tính năng này cho phép người dùng bắt đầu một hoạt động của ứng dụng trên một thiết bị Android và chuyển hoạt động đó sang một thiết bị Android khác. Tính năng Handoff chạy ở chế độ nền trên thiết bị của người dùng và hiển thị các hoạt động có sẵn từ các thiết bị khác ở gần của người dùng thông qua nhiều điểm truy cập, chẳng hạn như trình chạy và thanh tác vụ, trên thiết bị nhận.
Các ứng dụng có thể chỉ định tính năng Bàn giao để khởi chạy cùng một ứng dụng Android gốc, nếu ứng dụng đó được cài đặt và có trên thiết bị nhận. Trong quy trình từ ứng dụng đến ứng dụng này, người dùng được liên kết sâu đến hoạt động được chỉ định. Ngoài ra, bạn có thể cung cấp tính năng Bàn giao từ ứng dụng sang web dưới dạng lựa chọn dự phòng hoặc triển khai trực tiếp bằng tính năng Bàn giao URL.
Tính năng handoff được triển khai dựa trên từng hoạt động. Để bật tính năng Handoff, hãy gọi phương thức setHandoffEnabled() cho hoạt động. Bạn có thể cần chuyển thêm dữ liệu cùng với quá trình chuyển giao để hoạt động được tạo lại trên thiết bị nhận có thể khôi phục trạng thái thích hợp. Triển khai lệnh gọi lại onHandoffActivityRequested() để trả về một đối tượng HandoffActivityData chứa thông tin chi tiết chỉ định cách Handoff nên xử lý và tạo lại hoạt động trên thiết bị nhận.
Bản cập nhật trực tiếp – API màu sắc ngữ nghĩa
Với Android 17, Cập nhật trực tiếp sẽ ra mắt API Tô màu theo ngữ nghĩa để hỗ trợ các màu có ý nghĩa phổ quát.
Các lớp sau đây hỗ trợ tính năng tô màu theo ngữ nghĩa:
NotificationNotification.MetricNotification.ProgressStyle.PointNotification.ProgressStyle.Segment
Tô màu
- Màu xanh lục: Liên quan đến sự an toàn. Bạn nên dùng màu này trong trường hợp muốn cho mọi người biết rằng bạn đang ở trong tình huống an toàn.
- Màu cam: Dùng để chỉ sự thận trọng và đánh dấu các mối nguy hiểm vật lý. Bạn nên dùng màu này trong trường hợp người dùng cần chú ý để đặt chế độ bảo vệ tốt hơn.
- Màu đỏ: Thường biểu thị sự nguy hiểm, dừng lại. Bạn nên dùng màu này trong trường hợp cần thu hút sự chú ý của mọi người một cách khẩn cấp.
- Màu xanh dương: Màu trung tính cho nội dung mang tính thông tin và cần nổi bật so với nội dung khác.
Ví dụ sau đây cho biết cách áp dụng kiểu theo ngữ nghĩa cho văn bản trong một thông báo:
val ssb = SpannableStringBuilder()
.append("Colors: ")
.append("NONE", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_UNSPECIFIED), 0)
.append(", ")
.append("INFO", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_INFO), 0)
.append(", ")
.append("SAFE", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_SAFE), 0)
.append(", ")
.append("CAUTION", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_CAUTION), 0)
.append(", ")
.append("DANGER", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_DANGER), 0)
Notification.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_icon)
.setContentTitle("Hello World!")
.setContentText(ssb)
.setOngoing(true)
.setRequestPromotedOngoing(true)
UWB Downlink-TDoA API cho Android 17
Phạm vi Chênh lệch thời gian đến của đường xuống (DL-TDoA) cho phép thiết bị xác định vị trí của thiết bị so với nhiều điểm truy cập bằng cách đo thời gian đến tương đối của các tín hiệu.
Đoạn mã sau đây minh hoạ cách khởi tạo Trình quản lý đo khoảng cách, xác minh các chức năng của thiết bị và bắt đầu một phiên DL-TDoA:
Kotlin
class RangingApp {
fun initDlTdoa(context: Context) {
// Initialize the Ranging Manager
val rangingManager = context.getSystemService(RangingManager::class.java)
// Register for device capabilities
val capabilitiesCallback = object : RangingManager.CapabilitiesCallback {
override fun onRangingCapabilities(capabilities: RangingCapabilities) {
// Make sure Dl-TDoA is supported before starting the session
if (capabilities.uwbCapabilities != null && capabilities.uwbCapabilities!!.isDlTdoaSupported) {
startDlTDoASession(context)
}
}
}
rangingManager.registerCapabilitiesCallback(Executors.newSingleThreadExecutor(), capabilitiesCallback)
}
fun startDlTDoASession(context: Context) {
// Initialize the Ranging Manager
val rangingManager = context.getSystemService(RangingManager::class.java)
// Create session and configure parameters
val executor = Executors.newSingleThreadExecutor()
val rangingSession = rangingManager.createRangingSession(executor, RangingSessionCallback())
val rangingRoundIndexes = intArrayOf(0)
val config: ByteArray = byteArrayOf() // OOB config data
val params = DlTdoaRangingParams.createFromFiraConfigPacket(config, rangingRoundIndexes)
val rangingDevice = RangingDevice.Builder().build()
val rawTagDevice = RawRangingDevice.Builder()
.setRangingDevice(rangingDevice)
.setDlTdoaRangingParams(params)
.build()
val dtTagConfig = RawDtTagRangingConfig.Builder(rawTagDevice).build()
val preference = RangingPreference.Builder(DEVICE_ROLE_DT_TAG, dtTagConfig)
.setSessionConfig(SessionConfig.Builder().build())
.build()
// Start the ranging session
rangingSession.start(preference)
}
}
private class RangingSessionCallback : RangingSession.Callback {
override fun onDlTdoaResults(peer: RangingDevice, measurement: DlTdoaMeasurement) {
// Process measurement results here
}
}
Java
public class RangingApp {
public void initDlTdoa(Context context) {
// Initialize the Ranging Manager
RangingManager rangingManager = context.getSystemService(RangingManager.class);
// Register for device capabilities
RangingManager.CapabilitiesCallback capabilitiesCallback = new RangingManager.CapabilitiesCallback() {
@Override
public void onRangingCapabilities(RangingCapabilities capabilities) {
// Make sure Dl-TDoA is supported before starting the session
if (capabilities.getUwbCapabilities() != null && capabilities.getUwbCapabilities().isDlTdoaSupported) {
startDlTDoASession(context);
}
}
};
rangingManager.registerCapabilitiesCallback(Executors.newSingleThreadExecutor(), capabilitiesCallback);
}
public void startDlTDoASession(Context context) {
RangingManager rangingManager = context.getSystemService(RangingManager.class);
// Create session and configure parameters
Executor executor = Executors.newSingleThreadExecutor();
RangingSession rangingSession = rangingManager.createRangingSession(executor, new RangingSessionCallback());
int[] rangingRoundIndexes = new int[] {0};
byte[] config = new byte[0]; // OOB config data
DlTdoaRangingParams params = DlTdoaRangingParams.createFromFiraConfigPacket(config, rangingRoundIndexes);
RangingDevice rangingDevice = new RangingDevice.Builder().build();
RawRangingDevice rawTagDevice = new RawRangingDevice.Builder()
.setRangingDevice(rangingDevice)
.setDlTdoaRangingParams(params)
.build();
RawDtTagRangingConfig dtTagConfig = new RawDtTagRangingConfig.Builder(rawTagDevice).build();
RangingPreference preference = new RangingPreference.Builder(DEVICE_ROLE_DT_TAG, dtTagConfig)
.setSessionConfig(new SessionConfig.Builder().build())
.build();
// Start the ranging session
rangingSession.start(preference);
}
private static class RangingSessionCallback implements RangingSession.Callback {
@Override
public void onDlTdoaResults(RangingDevice peer, DlTdoaMeasurement measurement) {
// Process measurement results here
}
}
}
Cấu hình ngoài băng tần (OOB)
Đoạn mã sau đây cung cấp ví dụ về dữ liệu cấu hình DL-TDoA OOB cho Wi-Fi và BLE:
Java
// Wifi Configuration
byte[] wifiConfig = {
(byte) 0xDD, (byte) 0x2D, (byte) 0x5A, (byte) 0x18, (byte) 0xFF, // Header
(byte) 0x5F, (byte) 0x19, // FiRa Sub-Element
(byte) 0x02, (byte) 0x00, // Profile ID
(byte) 0x06, (byte) 0x02, (byte) 0x20, (byte) 0x08, // MAC Address
(byte) 0x14, (byte) 0x01, (byte) 0x0C, // Preamble Index
(byte) 0x27, (byte) 0x02, (byte) 0x08, (byte) 0x07, // Vendor ID
(byte) 0x28, (byte) 0x06, (byte) 0xCA, (byte) 0xC8, (byte) 0xA6, (byte) 0xF7, (byte) 0x6F, (byte) 0x08, // Static STS IV
(byte) 0x08, (byte) 0x02, (byte) 0x60, (byte) 0x09, // Slot Duration
(byte) 0x1B, (byte) 0x01, (byte) 0x0A, // Slots per RR
(byte) 0x09, (byte) 0x04, (byte) 0xE8, (byte) 0x03, (byte) 0x00, (byte) 0x00, // Duration
(byte) 0x9F, (byte) 0x04, (byte) 0x67, (byte) 0x45, (byte) 0x23, (byte) 0x01 // Session ID
};
// BLE Configuration
byte[] bleConfig = {
(byte) 0x2D, (byte) 0x16, (byte) 0xF4, (byte) 0xFF, // Header
(byte) 0x5F, (byte) 0x19, // FiRa Sub-Element
(byte) 0x02, (byte) 0x00, // Profile ID
(byte) 0x06, (byte) 0x02, (byte) 0x20, (byte) 0x08, // MAC Address
(byte) 0x14, (byte) 0x01, (byte) 0x0C, // Preamble Index
(byte) 0x27, (byte) 0x02, (byte) 0x08, (byte) 0x07, // Vendor ID
(byte) 0x28, (byte) 0x06, (byte) 0xCA, (byte) 0xC8, (byte) 0xA6, (byte) 0xF7, (byte) 0x6F, (byte) 0x08, // Static STS IV
(byte) 0x08, (byte) 0x02, (byte) 0x60, (byte) 0x09, // Slot Duration
(byte) 0x1B, (byte) 0x01, (byte) 0x0A, // Slots per RR
(byte) 0x09, (byte) 0x04, (byte) 0xE8, (byte) 0x03, (byte) 0x00, (byte) 0x00, // Duration
(byte) 0x9F, (byte) 0x04, (byte) 0x67, (byte) 0x45, (byte) 0x23, (byte) 0x01 // Session ID
};
Nếu không dùng được cấu hình OOB vì cấu hình này bị thiếu hoặc nếu cần thay đổi các giá trị mặc định không có trong cấu hình OOB, bạn có thể tạo các tham số bằng DlTdoaRangingParams.Builder như trong đoạn mã sau. Bạn có thể sử dụng các tham số này thay cho DlTdoaRangingParams.createFromFiraConfigPacket():
Kotlin
val dlTdoaParams = DlTdoaRangingParams.Builder(1)
.setComplexChannel(UwbComplexChannel.Builder()
.setChannel(9).setPreambleIndex(10).build())
.setDeviceAddress(deviceAddress)
.setSessionKeyInfo(byteArrayOf(0x01, 0x02, 0x03, 0x04))
.setRangingIntervalMillis(240)
.setSlotDuration(UwbRangingParams.DURATION_2_MS)
.setSlotsPerRangingRound(20)
.setRangingRoundIndexes(byteArrayOf(0x01, 0x05))
.build()
Java
DlTdoaRangingParams dlTdoaParams = new DlTdoaRangingParams.Builder(1)
.setComplexChannel(new UwbComplexChannel.Builder()
.setChannel(9).setPreambleIndex(10).build())
.setDeviceAddress(deviceAddress)
.setSessionKeyInfo(new byte[]{0x01, 0x02, 0x03, 0x04})
.setRangingIntervalMillis(240)
.setSlotDuration(UwbRangingParams.DURATION_2_MS)
.setSlotsPerRangingRound(20)
.setRangingRoundIndexes(new byte[]{0x01, 0x05})
.build();