Khả năng tương thích ngược cho Thời gian chạy SDK

Tài liệu này đề xuất một thư viện Jetpack mới giúp nhà phát triển di chuyển sang Thời gian chạy SDK. Tài liệu này giải thích xem Thời gian chạy SDK sẽ được hỗ trợ như thế nào cho các phiên bản cũ của nền tảng Android (từ bản dựng đến quá trình thực thi), cũng như những điểm khác biệt hoặc hạn chế trong môi trường thời gian chạy mà nhà phát triển có thể mong đợi. Thư viện này cho phép nhà phát triển tạo một phiên bản ứng dụng hoặc SDK duy nhất có khả năng chạy trên các thiết bị có hoặc không hỗ trợ Thời gian chạy SDK.

Khả năng tương thích ngược đạt được thông qua các thành phần sau:

  • Trình bổ trợ Android cho Gradle (AGP) + Bundletool tạo ra một biến thể ứng dụng cho các thiết bị không hỗ trợ Thời gian chạy SDK bằng cách nhóm Thời gian chạy SDK vào tệp APK.

  • Thư viện ứng dụng Thời gian chạy SDK (androidx.privacysandbox.sdkruntime:sdkruntime-client) tải SDK đi kèm từ các thành phần ứng dụng và mô phỏng Thời gian chạy SDK trên các thiết bị không hỗ trợ Thời gian chạy SDK.

  • Thư viện nhà cung cấp Thời gian chạy SDK (androidx.privacysandbox.sdkruntime:sdkruntime-provider) cung cấp một API cho các SDK để cho phép tải từ thư viện ứng dụng Thời gian chạy SDK.

Phân phối SDK bằng Bundletool

Trên các thiết bị có hỗ trợ Thời gian chạy SDK, SDK sẽ được phân phối và cài đặt dưới dạng các gói riêng biệt.

Để hỗ trợ các phiên bản nền tảng không hỗ trợ Thời gian chạy SDK, Bundletool sẽ tạo một hoặc nhiều biến thể của tập hợp tệp APK ứng dụng bao gồm tất cả các SDK mà ứng dụng phụ thuộc. Mỗi SDK được đóng gói dưới dạng một phần phân tách APK riêng biệt. Hơn nữa, bạn còn thực hiện các phép biến đổi sau:

  1. Sao chép các tệp mã byte SDK (DEX) vào phần phân tách SDK dưới dạng các thành phần.
  2. Sao chép các tài nguyên Java của SDK vào phần phân tách SDK dưới dạng các thành phần.
  3. Liên kết lại rồi hợp nhất các tài nguyên SDK với các tài nguyên ứng dụng.
  4. Tạo các cấu hình cho thư viện ứng dụng Thời gian chạy SDK.

Tải các SDK bằng thư viện ứng dụng Thời gian chạy SDK

Thư viện ứng dụng Thời gian chạy SDK cung cấp các API tương tự như API nền tảng, nhưng hỗ trợ cả SDK trong môi trường Thời gian chạy SDK và các SDK đi kèm với ứng dụng biến thể này.

Để sử dụng thư viện ứng dụng Thời gian chạy SDK, hãy thêm phần phụ thuộc androidx.privacysandbox.sdkruntime:sdkruntime-client và sử dụng SdkSandboxManagerCompat thay vì SdkSandboxManager.

Khi một ứng dụng cố gắng tải một SDK, trước tiên, thư viện sẽ kiểm tra xem SDK có được đi kèm với ứng dụng trong quá trình tạo bản dựng hay không. Nếu đã đi kèm, thư viện sẽ trích xuất SDK từ phần phân tách SDK và tải SDK đó vào quy trình ứng dụng. Nếu SDK không được đi kèm với ứng dụng, thì thư viện sẽ uỷ quyền API nền tảng để tải SDK đó.

Trích xuất một SDK từ các thành phần

Khi một ứng dụng cố tải một SDK đi kèm, thư viện ứng dụng Thời gian chạy SDK sẽ kiểm tra xem các tệp DEX của SDK đó đã được trích xuất vào bộ nhớ thiết bị (code_cache) hay chưa (nếu chưa, thì sẽ trích xuất những tệp đó từ các thành phần).

Thông thường, thư viện sẽ chỉ trích xuất các tệp một lần sau khi cài đặt hoặc cập nhật ứng dụng.

Nếu dung lượng lưu trữ còn trống thấp hơn ngưỡng cho phép (hiện là 100 MB) và không có tệp DEX nào được trích xuất, thì thư viện sẽ cố gắng tải SDK trực tiếp từ các thành phần trên những thiết bị được hỗ trợ (API cấp 27 trở lên). Điều này dẫn đến mức sử dụng bộ nhớ lớn hơn.

Trình tải lớp cho các lớp SDK

Để tránh xung đột giữa SDK và lớp ứng dụng, tất cả các lớp SDK đều được tải bằng một trình tải lớp riêng biệt, hoàn toàn độc lập với trình tải lớp chính của ứng dụng.

Trong thiết kế Thời gian chạy SDK hiện tại, mọi hoạt động giao tiếp giữa một ứng dụng và SDK đều diễn ra qua các lệnh gọi Binder IPC. Các đối tượng SDK Binder tương tự được dùng cho các SDK đi kèm. Tính năng chuyển đổi tuần tự giao dịch Binder cho phép nhà phát triển ứng dụng truyền các đối tượng SDK Binder sang các giao diện SDK Binder ở phía ứng dụng.

Đối với các hoạt động tương tác nội bộ khác (chẳng hạn như khởi chạy SDK, cung cấp API bộ điều khiển cho SDK, v.v.), thư viện sẽ sử dụng Proxy phản chiếu và Proxy động để hoạt động được trên nhiều trình tải lớp.

Môi trường SDK

Thư viện Nhà cung cấp SDKRuntime cung cấp các API cho nhà phát triển SDK. Các API này tương tự như các API nền tảng, nhưng cho phép tải SDK bằng cả môi trường Thời gian chạy SDK và thư viện Ứng dụng SDKRuntime.

Để có thể sử dụng SDK thư viện này, bạn cần thêm phần phụ thuộc androidx.privacysandbox.sdkruntime:sdkruntime-provider và mở rộng SandboxedSdkProviderCompat thay vì SandboxedSdkProvider.

Bạn cũng cần sử dụng SandboxedSdkProviderAdapter làm nhà cung cấp SDK để cho phép tải nhà cung cấp khả năng tương thích trong môi trường Thời gian chạy SDK.

SdkSandboxControllerCompat uỷ quyền cho API nền tảng khi SDK được tải trong Thời gian chạy SDK hoặc uỷ quyền cho thư viện Ứng dụng SDKRuntime khi SDK được tải dưới dạng một SDK đi kèm.

Đối với các SDK đi kèm, thư viện này sẽ sửa đổi môi trường SDK theo cách mô phỏng hành vi tương tự với môi trường Thời gian chạy SDK.

Các phần tiếp theo mô tả các hành vi dự kiến khi SDK được tải bằng thư viện Ứng dụng SDKRuntime.

Các tài nguyên SDK

Các tài nguyên SDK (res/) được hỗ trợ khi SDK được tải trong quy trình của ứng dụng. Bundletool sẽ hợp nhất tất cả các tài nguyên của SDK với tài nguyên của ứng dụng.

Để tránh xung đột, các tài nguyên SDK sẽ được liên kết lại bằng cách thay đổi tiền tố packageId trong mọi mã tài nguyên.

Khi thư viện Ứng dụng SDKRuntime tải SDK, packageId sẽ được cập nhật trong thời gian chạy để cho phép xử lý các tài nguyên đã liên kết lại bằng lớp R.

Các tài nguyên Java

Các tài nguyên Java được hỗ trợ khi SDK được tải trong quy trình của ứng dụng. Bundletool sẽ sao chép tất cả các tài nguyên SDK Java vào một thư mục đặc biệt trong các thành phần ứng dụng. Thư viện Ứng dụng SDKRuntime sẽ dùng một trình tải lớp trung gian để chuyển hướng tất cả các lệnh gọi liên quan đến tài nguyên Java đến thư mục gốc mới.

Các thành phần SDK

Các thành phần SDK được hợp nhất với các thành phần ứng dụng mà không cần liên kết lại.

Bộ nhớ SDK

Để hỗ trợ Bộ nhớ SDK, thư viện ứng dụng Thời gian chạy SDK sẽ tạo một thư mục gốc dành riêng cho mỗi SDK đi kèm trong bộ nhớ ứng dụng và cung cấp một ngữ cảnh đặc biệt sử dụng thư mục này làm thư mục gốc của bộ nhớ.

Ngữ cảnh này có thể được truy xuất từ SandboxedSdkProviderCompat#getContext.

Các phương thức liên quan đến bộ nhớ được hỗ trợ:

  • getDataDir
  • getCacheDir
  • getCodeCacheDir
  • getNoBackupFilesDir
  • getDir
  • getFilesDir
  • openFileInput
  • openFileOutput
  • deleteFile
  • getFileStreamPath
  • fileList
  • getDatabasePath
  • openOrCreateDatabase
  • moveDatabaseFrom – chỉ trong các ngữ cảnh SDK
  • deleteDatabase
  • databaseList
  • getSharedPreferences
  • moveSharedPreferencesFrom – chỉ trong các ngữ cảnh SDK
  • deleteSharedPreferences

Ngữ cảnh bộ nhớ được bảo vệ của thiết bị được tạo bằng cách gọi createDeviceProtectedStorageContext() trên ngữ cảnh đó.

SdkSandboxControllerCompat

Thư viện ứng dụng SDKRuntime cung cấp phương thức triển khai SdkSandboxControllerCompat cho các SDK đi kèm (được tải trong quy trình ứng dụng).

Nếu thư viện ứng dụng không hỗ trợ các API (ví dụ: với một SDK được tạo bằng phiên bản thư viện mới hơn phiên bản ứng dụng đó), thì API dự phòng phù hợp nhất sẽ được sử dụng (không hoạt động hoặc ngoại lệ).

Lập phiên bản

Khi thư viện Ứng dụng SDKRuntime tải một SDK đi kèm, thư viện này sẽ bắt tay với thư viện Nhà cung cấp SDKRuntime bên trong SDK đó. Trong quá trình bắt tay, các thư viện sẽ trao đổi phiên bản và điều chỉnh hành vi để thay thế các API không có sẵn bằng API dự phòng phù hợp nhất (không hoạt động hoặc ngoại lệ).

Bạn nên sử dụng phiên bản thư viện mới nhất cho cả Nhà phát triển ứng dụng và Nhà phát triển SDK, nếu không thì có thể không dùng được các chức năng cần hỗ trợ ở cả hai phần.

Mọi phiên bản thư viện Ứng dụng SDKRuntime đều có thể tải một SDK bằng bất kỳ phiên bản nào của thư viện Nhà cung cấp SDKRuntime và ngược lại.

Trong tương lai, thư viện này sẽ được thay đổi thành phiên bản thư viện ứng dụng tối thiểu cần thiết để tải SDK bằng một phiên bản cụ thể của thư viện nhà cung cấp.

Việc này sẽ giảm thiểu tình trạng phân mảnh và đảm bảo rằng hầu hết các API sẽ được hỗ trợ nếu bạn tải thành công SDK đi kèm.