Các hạn chế đối với giao diện không phải SDK

Kể từ Android 9 (API cấp 28), nền tảng này sẽ hạn chế các giao diện không phải SDK mà ứng dụng của bạn có thể sử dụng. Các hạn chế này áp dụng mỗi khi ứng dụng tham chiếu đến một giao diện không phải SDK hoặc cố gắng nhận xử lý bằng cách sử dụng cơ chế phản chiếu (reflection) hoặc JNI. Những hạn chế này được áp dụng nhằm giúp cải thiện trải nghiệm của người dùng và nhà phát triển, đồng thời giảm nguy cơ xảy ra sự cố cho người dùng cũng như trong quá trình phát hành khẩn cấp cho nhà phát triển. Để biết thêm thông tin về quyết định này, hãy xem nội dung Cải thiện độ ổn định bằng cách giảm mức sử dụng giao diện không phải SDK.

Phân biệt giao diện SDK và giao diện không phải SDK

Nhìn chung, giao diện SDK công khai là những giao diện xuất hiện trong chỉ mục gói (Package Index) của khung Android. Hoạt động xử lý giao diện không phải SDK là thông tin triển khai chi tiết mà API sẽ tóm tắt, vì vậy, các giao diện này có thể thay đổi mà không cần thông báo trước.

Để tránh sự cố và hành vi không mong muốn, ứng dụng chỉ nên sử dụng các phần được ghi chính thức của các lớp trong SDK. Tức là bạn không nên truy cập các phương thức hoặc trường không được liệt kê trong SDK khi tương tác với một lớp qua các cơ chế như cơ chế phản chiếu.

Danh sách API không phải SDK

Với mỗi bản phát hành Android, các giao diện không phải SDK khác cũng bị hạn chế. Chúng tôi hiểu rằng những hạn chế này có thể ảnh hưởng đến quy trình phát hành của bạn. Vì vậy, chúng tôi muốn đảm bảo bạn có các công cụ để phát hiện hoạt động sử dụng giao diện không phải SDK, một cơ hội để gửi phản hồi cho chúng tôi cũng như thời gian để lập kế hoạch và điều chỉnh theo các chính sách mới.

Nhằm giảm thiểu tác động của các quy định hạn chế không liên quan đến SDK đối với quy trình phát triển của bạn, các giao diện không phải SDK sẽ được chia thành các danh sách xác định mức độ hạn chế của việc sử dụng các SDK đó, tuỳ thuộc vào cấp API bạn đang nhắm đến. Bảng sau đây mô tả từng loại trong những danh sách này:

Danh sách Mô tả
Danh sách chặn (blacklist) Giao diện không phải SDK mà bạn không thể sử dụng bất kể cấp độ API mục tiêu của ứng dụng. Nếu ứng dụng của bạn cố gắng truy cập một trong những giao diện này, thì hệ thống sẽ đưa ra lỗi.
Chặn có điều kiện (greylist-max-x)

Kể từ Android 9 (API cấp 28), mỗi cấp độ API sẽ chứa các giao diện không phải SDK bị hạn chế khi một ứng dụng nhắm đến cấp độ API đó.

Các danh sách này được gắn nhãn theo cấp API tối đa (max-target-x) mà một ứng dụng có thể nhắm đến trước khi ứng dụng đó không thể truy cập các giao diện không phải SDK trong danh sách đó nữa. Ví dụ: một giao diện không phải SDK mà trước đây không bị chặn trong Android Pie nhưng hiện bị chặn trong Android 10, sẽ thuộc danh sách max-target-p (greylist-max-p), trong đó "p" là viết tắt của Pie hoặc Android 9 (API cấp 28).

Nếu ứng dụng của bạn cố gắng truy cập vào một giao diện bị hạn chế ở cấp độ API mục tiêu, thì hệ thống sẽ coi như API đó thuộc danh sách chặn.

Không hỗ trợ (greylist) Giao diện không phải SDK hiện không bị hạn chế và ứng dụng của bạn có thể sử dụng. Tuy nhiên, xin lưu ý rằng những giao diện này không được hỗ trợ và có thể thay đổi mà không cần thông báo trước. Có thể những giao diện này sẽ bị chặn có điều kiện trong các phiên bản Android sau này trong danh sách max-target-x.
SDK (whitelist) Các giao diện có thể sử dụng thoải mái và hiện được hỗ trợ trong khung Chỉ mục gói (Package Index) được ghi lại chính thức của Android.

Mặc dù bạn hiện có thể sử dụng một số giao diện không phải SDK (tuỳ thuộc vào cấp độ API mục tiêu của ứng dụng), nhưng hoạt động sử dụng phương thức hoặc trường bất kỳ không phải SDK luôn có nguy cơ cao làm hỏng ứng dụng. Nếu ứng dụng của bạn dựa vào giao diện không phải SDK, thì bạn nên bắt đầu lập kế hoạch di chuyển sang giao diện SDK hoặc các giải pháp thay thế khác. Nếu không tìm được giải pháp thay thế cho hoạt động sử dụng giao diện không phải SDK cho một tính năng trong ứng dụng, thì bạn nên yêu cầu một API công khai mới.

Xác định xem giao diện thuộc danh sách nào

Danh sách giao diện không phải SDK được xây dựng trong nền tảng. Hãy xem các phần dưới đây để nắm thông tin về từng bản phát hành Android.

Android 13 phiên bản thử nghiệm

Đối với Android 13 (API cấp 33), bạn có thể tải tệp sau đây xuống. Tệp này mô tả tất cả các giao diện không phải SDK và danh sách tương ứng:

Tệp: hiddenapi-flags.csv

Giá trị tổng kiểm SHA-256: 2886a24b6382be8751e86e3c355516c448987c3b0550eb8bb906a34490cfaa3c

Để tìm hiểu thêm về thay đổi đối với danh sách API không phải SDK trong Android 13, bao gồm các lựa chọn thay thế API công khai được đề xuất đối với các API bị chặn có điều kiện trong Android 13, vui lòng xem bài viết Cập nhật đối với những hạn chế về giao diện không phải SDK trong Android 13.

Android 12

Đối với Android 12 (API cấp 31), bạn có thể tải tệp sau đây xuống. Tệp này mô tả tất cả giao diện không phải SDK và danh sách tương ứng.

Tệp: hiddenapi-flags.csv

Giá trị tổng kiểm SHA-256: 40674ff4291eb268f86561bf687e69dbd013df9ec9531a460404532a4ac9a761

Để tìm hiểu thêm về những thay đổi đối với danh sách API không phải SDK trong Android 12, kể cả các giải pháp thay thế API công khai được đề xuất cho API bị chặn có điều kiện trong Android 12, hãy xem nội dung Thay đổi đối với danh sách trong Android 12.

Android 11

Đối với Android 11 (API cấp 30), bạn có thể tải tệp sau đây xuống. Tệp này mô tả tất cả giao diện không phải SDK và danh sách tương ứng.

Tệp: hiddenapi-flags.csv

Giá trị tổng kiểm SHA-256: a19d839f4f61dc9c94960ae977b2e0f3eb30f880ba1ffe5108e790010b477a56

Để tìm hiểu thêm về những thay đổi đối với danh sách API không phải SDK trong Android 11, kể cả các phương án thay thế API công khai được đề xuất cho API bị chặn có điều kiện trong Android 11, hãy xem nội dung Thay đổi đối với danh sách trong Android 11.

Android 10

Đối với Android 10 (API cấp 29), bạn có thể tải tệp sau đây xuống. Tệp này mô tả tất cả giao diện không phải SDK và danh sách tương ứng.

Tệp: hiddenapi-flags.csv

Giá trị tổng kiểm SHA-256: f22a59c215e752777a114bd9b07b0b6b4aedfc8e49e6efca0f99681771c5bfeb

Để tìm hiểu thêm về những thay đổi đối với danh sách API không phải SDK trong Android 10, kể cả các giải pháp thay thế API công khai được đề xuất cho API bị chặn có điều kiện trong Android 10, hãy xem nội dung Thay đổi đối với danh sách trong Android 10.

Android 9

Đối với Android 9 (API cấp 28), tệp văn bản sau đây chứa danh sách API không phải SDK không bị hạn chế (được liệt kê vào danh sách xám): hiddenapi-light-greylist.txt.

Danh sách chặn (blacklist) và danh sách API bị chặn có điều kiện (danh sách xám đen) được bắt nguồn từ thời điểm tạo bản dựng.

Tạo danh sách qua AOSP (Dự án nguồn mở Android)

Khi làm việc với AOSP, bạn có thể tạo tệp hiddenapi-flags.csv chứa tất cả giao diện không phải SDK và danh sách tương ứng. Để thực hiện việc này, hãy tải nguồn AOSP xuống rồi chạy lệnh sau:

m out/soong/hiddenapi/hiddenapi-flags.csv

Sau đó, bạn có thể tìm thấy tệp này ở vị trí sau:

out/soong/hiddenapi/hiddenapi-flags.csv

Hành vi dự kiến khi truy cập giao diện bị hạn chế không phải SDK

Bảng sau đây mô tả hành vi mà bạn có thể lường trước nếu ứng dụng của bạn cố gắng truy cập vào một giao diện không phải SDK thuộc danh sách chặn.

Phương tiện truy cập Kết quả
Hướng dẫn Dalvik tham chiếu trường Gửi NoSuchFieldError
Hướng dẫn Dalvik tham chiếu phương pháp Gửi NoSuchMethodError
Phản chiếu qua Class.getDeclaredField() hoặc Class.getField() Gửi NoSuchFieldException
Phản chiếu qua Class.getDeclaredMethod(), Class.getMethod() Gửi NoSuchMethodException
Phản chiếu qua Class.getDeclaredFields(), Class.getFields() Thành viên không phải SDK trong kết quả
Phản chiếu qua Class.getDeclaredMethods(), Class.getMethods() Thành viên không phải SDK trong kết quả
JNI qua env->GetFieldID() Trả về NULL, gửi NoSuchFieldError
JNI qua env->GetMethodID() Trả về NULL, gửi NoSuchMethodError

Kiểm thử giao diện không phải SDK trên ứng dụng

Có một số phương pháp mà bạn có thể sử dụng để kiểm thử giao diện không phải SDK trên ứng dụng.

Kiểm thử bằng ứng dụng có thể gỡ lỗi

Bạn có thể kiểm tra giao diện không phải SDK bằng cách tạo và chạy một ứng dụng có thể gỡ lỗi trên thiết bị hoặc trình mô phỏng chạy Android 9 (API cấp 28) trở lên. Hãy đảm bảo rằng thiết bị hoặc trình mô phỏng mà bạn đang sử dụng khớp với cấp độ API mục tiêu của ứng dụng.

Trong khi chạy kiểm thử trên ứng dụng, hệ thống sẽ in một thông điệp nhật ký nếu ứng dụng của bạn truy cập một số giao diện cụ thể không phải SDK. Bạn có thể kiểm thử thông điệp nhật ký của ứng dụng để tìm những thông tin chi tiết sau:

  • Lớp (class), tên (name) và kiểu (type) khai báo (ở định dạng mà Android Runtime sử dụng).
  • Phương tiện truy cập: liên kết, thông qua cơ chế phản chiếu hoặc qua JNI.
  • Giao diện không phải SDK thuộc danh sách nào.

Bạn có thể sử dụng adb logcat để truy cập những thông điệp nhật ký này; chúng xuất hiện trong PID của ứng dụng đang chạy. Ví dụ: có thể đọc một mục trong nhật ký như sau:

Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)

Kiểm thử bằng StrictMode API

Bạn cũng có thể kiểm thử các giao diện không phải SDK bằng cách sử dụng StrictMode API. Sử dụng phương thức detectNonSdkApiUsage để bật tính năng này. Sau khi bật StrictMode API, bạn có thể nhận lệnh gọi lại cho mỗi lần sử dụng giao diện không phải SDK bằng cách sử dụng penaltyListener, trong đó bạn có thể triển khai cách xử lý tuỳ chỉnh. Đối tượng Violation được cung cấp trong lệnh gọi lại xuất phát từ Throwable và dấu vết ngăn xếp kèm theo cho biết ngữ cảnh sử dụng.

Kiểm thử bằng công cụ veridex

Bạn cũng có thể chạy công cụ phân tích tĩnh veridex trên tệp APK. Công cụ veridex quét toàn bộ cơ sở mã của tệp APK (bao gồm cả mọi thư viện của bên thứ ba) và báo cáo mọi lần sử dụng giao diện không phải SDK mà công cụ này tìm thấy.

Công cụ veridex có một số hạn chế như sau:

  • Không phát hiện được lệnh gọi qua JNI.
  • Chỉ phát hiện được một tập hợp con lệnh gọi qua phản chiếu.
  • Số liệu phân tích về các đường dẫn mã không hoạt động chỉ áp dụng cho các lượt kiểm tra cấp độ API.
  • Chỉ có thể chạy trên các máy hỗ trợ hướng dẫn SSE4.2 và POPCNT.

Windows

Bạn chưa cung cấp tệp nhị phân Windows gốc, nhưng bạn có thể chạy công cụ trình duyệt trên Windows bằng cách thực thi tệp nhị phân Linux bằng Windows Subsystem for Linux (WSL). Trước khi làm theo các bước trong phần này, hãy cài đặt WSL và chọn Ubuntu làm bản phân phối Linux.

Sau khi cài đặt Ubuntu, hãy chạy một thiết bị đầu cuối Ubuntu rồi làm theo những bước sau:

  1. Tải công cụ veridex qua kho lưu trữ tạo sẵn cho Android Runtime.
  2. Trích xuất nội dung của tệp appcompat.tar.gz.
  3. Trong thư mục đã giải nén, hãy tìm tệp veridex-linux.zip rồi giải nén tệp này.
  4. Chuyển đến thư mục đã giải nén rồi chạy lệnh sau, trong đó your-app.apk là tệp APK mà bạn muốn kiểm thử:

    ./appcompat.sh --dex-file=your-app.apk
    

macOS

Để chạy công cụ veridex trên macOS, hãy làm theo các bước sau:

  1. Tải công cụ veridex qua kho lưu trữ tạo sẵn cho Android Runtime.
  2. Trích xuất nội dung của tệp appcompat.tar.gz.
  3. Trong thư mục đã giải nén, hãy tìm tệp veridex-mac.zip rồi giải nén tệp này.
  4. Chuyển đến thư mục đã giải nén rồi chạy lệnh sau, trong đó /path-from-root/your-app.apk là đường dẫn đến tệp APK mà bạn muốn kiểm thử, bắt đầu từ thư mục gốc của hệ thống:

    ./appcompat.sh --dex-file=/path-from-root/your-app.apk
    

Linux

Để chạy công cụ veridex trên Linux, hãy làm theo các bước sau:

  1. Tải công cụ veridex qua kho lưu trữ tạo sẵn cho Android Runtime.
  2. Trích xuất nội dung của tệp appcompat.tar.gz.
  3. Trong thư mục đã giải nén, hãy tìm tệp veridex-linux.zip rồi giải nén tệp này.
  4. Chuyển đến thư mục đã giải nén rồi chạy lệnh sau, trong đó your-app.apk là tệp APK mà bạn muốn kiểm thử:

    ./appcompat.sh --dex-file=your-app.apk
    

Kiểm thử bằng công cụ tìm lỗi mã nguồn của Android Studio

Bất cứ khi nào bạn xây dựng ứng dụng trong Android Studio, công cụ tìm lỗi mã nguồn sẽ kiểm tra mã nguồn của bạn để tìm các vấn đề tiềm ẩn. Nếu ứng dụng của bạn sử dụng giao diện không phải SDK, thì bạn có thể thấy lỗi bản dựng hoặc cảnh báo, tuỳ thuộc vào việc giao diện đó thuộc danh sách nào.

Bạn cũng có thể chạy công cụ tìm lỗi mã nguồn qua dòng lệnh hoặc chạy kiểm thử theo cách thủ công trên một dự án, thư mục hoặc tệp cụ thể.

Kiểm thử bằng Play Console

Khi bạn tải ứng dụng lên một kênh thử nghiệm trong Play Console, ứng dụng của bạn sẽ được tự động kiểm thử để tìm các vấn đề tiềm ẩn và báo cáo trước khi ra mắt sẽ được tạo. Nếu ứng dụng của bạn sử dụng giao diện không phải SDK, thì lỗi hoặc cảnh báo sẽ xuất hiện trong báo cáo trước khi ra mắt, tuỳ thuộc vào việc giao diện đó thuộc danh sách nào.

Để biết thêm thông tin, hãy xem phần Khả năng tương thích với Android trong nội dung Sử dụng báo cáo trước khi ra mắt để xác định các vấn đề.

Yêu cầu API công khai mới

Nếu không tìm được giải pháp thay thế cho hoạt động sử dụng giao diện không phải SDK cho một tính năng trong ứng dụng, thì bạn có thể yêu cầu API công khai mới bằng cách tạo yêu cầu về tính năng trong công cụ theo dõi lỗi của chúng tôi.

Khi tạo yêu cầu tính năng, hãy cung cấp những thông tin sau:

  • API có trong danh sách xám mà bạn đang sử dụng (bao gồm cả phần mô tả đầy đủ trong thông báo logcat Accessing hidden ...).
  • Tại sao bạn cần sử dụng các API đó, bao gồm cả thông tin chi tiết về tính năng cấp cao mà API cần đến, chứ không chỉ thông tin chi tiết về cấp thấp.
  • Tại sao mọi API công khai liên quan đều chưa đáp ứng được mục đích của bạn.
  • Mọi giải pháp thay thế khác mà bạn đã thử và lý do chúng đều không hiệu quả.

Khi bạn cung cấp những thông tin chi tiết này trong yêu cầu về tính năng, khả năng được cấp API công khai mới sẽ tăng lên.

Câu hỏi khác

Phần này bao gồm câu trả lời cho một số câu hỏi khác mà nhà phát triển hay hỏi:

Câu hỏi chung

Làm cách nào để Google chắc chắn rằng họ sẽ nắm bắt được nhu cầu của tất cả ứng dụng thông qua công cụ theo dõi lỗi?

Chúng tôi đã tạo các danh sách ban đầu cho Android 9 (API cấp 28) thông qua bản phân tích tĩnh về các ứng dụng đã được bổ sung bằng các phương thức sau:

  • kiểm thử thủ công các ứng dụng hàng đầu trên Play và ngoài Play
  • báo cáo nội bộ
  • tự động thu thập dữ liệu qua người dùng nội bộ
  • báo cáo bản dùng thử cho nhà phát triển
  • bản phân tích tĩnh bổ sung được thiết kế để tính thêm kết quả dương tính giả một cách thận trọng

Khi đánh giá danh sách cho mỗi bản phát hành mới, chúng tôi xem xét hoạt động sử dụng API cũng như phản hồi của nhà phát triển thông qua công cụ theo dõi lỗi.

Làm cách nào để tôi có thể cho phép truy cập vào giao diện không phải SDK?

Bạn có thể cho phép truy cập vào các giao diện không phải SDK trên thiết bị phát triển bằng cách sử dụng các lệnh adb để thay đổi chính sách thực thi API. Các lệnh mà bạn sử dụng còn tuỳ thuộc vào cấp độ API. Các lệnh này không đòi hỏi thiết bị bị can thiệp hệ thống.

Android 10 (API cấp 29) trở lên

Để cho phép truy cập, hãy sử dụng lệnh adb sau:

adb shell settings put global hidden_api_policy  1

Để đặt lại chính sách thực thi API về chế độ cài đặt mặc định, hãy sử dụng lệnh sau:

adb shell settings delete global hidden_api_policy
Android 9 (API cấp 28)

Để cho phép truy cập, hãy sử dụng các lệnh adb sau:

adb shell settings put global hidden_api_policy_pre_p_apps  1
adb shell settings put global hidden_api_policy_p_apps 1

Để đặt lại chính sách thực thi API về chế độ cài đặt mặc định, hãy sử dụng các lệnh sau:

adb shell settings delete global hidden_api_policy_pre_p_apps
adb shell settings delete global hidden_api_policy_p_apps

Bạn có thể đặt số nguyên trong chính sách thực thi API thành một trong các giá trị sau:

  • 0: Vô hiệu hoá tất cả giao diện người dùng không phải SDK. Việc sử dụng chế độ cài đặt này sẽ vô hiệu hoá tất cả thông điệp nhật ký về mức sử dụng giao diện không phải SDK và ngăn bạn kiểm thử ứng dụng bằng cách sử dụng API StrictMode. Bạn không nên sử dụng chế độ cài đặt này.
  • 1: Cho phép truy cập tất cả giao diện không phải SDK, nhưng in thông điệp nhật ký kèm theo cảnh báo đối với mọi hoạt động sử dụng giao diện không phải SDK. Khi sử dụng chế độ cài đặt này, bạn cũng có thể kiểm thử ứng dụng bằng StrictMode API.
  • 2: Không cho phép sử dụng giao diện không phải SDK thuộc danh sách chặn hoặc bị chặn có điều kiện cho cấp độ API mục tiêu của bạn.

Câu hỏi về danh sách giao diện không phải SDK

Tôi có thể tìm thấy các danh sách API không phải SDK ở đâu trong ảnh hệ thống?

Chúng được mã hoá trong các bit cờ truy cập trường và phương thức trong các tệp dex nền tảng. Không có tệp riêng biệt nào trong ảnh hệ thống cho thấy các danh sách này.

Danh sách API không phải SDK có như nhau trên các thiết bị của nhà sản xuất thiết bị gốc (OEM) có cùng phiên bản Android không?

OEM có thể thêm giao diện riêng vào danh sách chặn (danh sách cấm) nhưng không thể xoá giao diện khỏi danh sách API AOSP không phải SDK. CDD ngăn chặn những thay đổi như vậy và các chương trình kiểm thử CTS giúp đảm bảo rằng Android Runtime thực thi danh sách.

Có quy định hạn chế nào đối với giao diện không phải NDK trong mã gốc không?

SDK Android bao gồm cả giao diện Java. Nền tảng này đã bắt đầu hạn chế quyền truy cập giao diện không phải NDK đối với mã C/C++ gốc trong Android 7 (API cấp 26). Để biết thêm thông tin, hãy xem nội dung Cải thiện độ ổn định bằng quy định hạn chế biểu tượng C/C++ riêng tư trong Android N.

Google có dự định hạn chế thao tác nào đối với tệp dex2oat hoặc DEX không?

Chúng tôi không có các kế hoạch chủ động để hạn chế quyền truy cập tệp nhị phân dex2oat, nhưng chúng tôi không có ý định ổn định định dạng tệp DEX hoặc giao diện công khai ngoài các phần được chỉ định công khai trong định dạng có thể thực thi Dalvik. Chúng tôi giữ quyền sửa đổi hoặc loại bỏ dex2oat và các phần chưa được chỉ định của định dạng DEX vào bất cứ lúc nào. Ngoài ra, xin lưu ý rằng các tệp bắt nguồn từ dex2oat như ODEX (còn gọi là OAT), VDEX và CDEX đều là các định dạng không xác định.

Nếu một SDK quan trọng của bên thứ ba (ví dụ: một trình làm rối mã nguồn) không thể tránh việc sử dụng giao diện không phải SDK nhưng lại cam kết duy trì khả năng tương thích với các phiên bản Android trong tương lai thì sao? Trong trường hợp này, Android có thể từ bỏ các yêu cầu về khả năng tương thích không?

Chúng tôi không có kế hoạch từ bỏ các yêu cầu về khả năng tương thích trên mỗi SDK. Nếu nhà phát triển SDK hiện chỉ có thể duy trì khả năng tương thích bằng cách dựa vào các giao diện trong danh sách không được hỗ trợ (trước đây là danh sách xám), thì họ nên bắt đầu lên kế hoạch chuyển sang giao diện SDK hoặc các phương án thay thế khác và yêu cầu API công khai mới bất cứ khi nào không tìm được giải pháp thay thế cho việc sử dụng giao diện không phải SDK.

Các quy định hạn chế đối với giao diện không phải SDK có áp dụng cho tất cả ứng dụng (bao gồm cả ứng dụng hệ thống và ứng dụng bên thứ nhất, không chỉ ứng dụng bên thứ ba) hay không?

Có, tuy nhiên, chúng tôi miễn trừ các ứng dụng được ký bằng khoá nền tảng và một số ứng dụng ảnh hệ thống. Xin lưu ý rằng các trường hợp miễn trừ này chỉ áp dụng cho các ứng dụng thuộc ảnh hệ thống (hoặc ứng dụng ảnh hệ thống mới cập nhật). Danh sách này chỉ dành cho các ứng dụng xây dựng dựa trên API nền tảng riêng tư, thay vì API SDK (khi LOCAL_PRIVATE_PLATFORM_APIS := true).