Kết quả về tính toàn vẹn

Trang này mô tả cách diễn giải và xử lý kết quả về tính toàn vẹn được trả về. Cho dù bạn thực hiện yêu cầu API thông thường hay yêu cầu API kiểu cũ, kết quả về tính toàn vẹn sẽ được trả về ở cùng định dạng với nội dung tương tự. Kết quả về tính toàn vẹn sẽ cho biết thông tin về tính hợp lệ của các thiết bị, ứng dụng và tài khoản. Máy chủ của ứng dụng có thể dùng tải trọng phát sinh trong một kết quả đã được giải mã và xác minh nhằm xác định cách tốt nhất để xử lý một hành động hoặc yêu cầu cụ thể trong ứng dụng của bạn.

Định dạng của kết quả về tính toàn vẹn được trả về

Tải trọng này là tệp JSON văn bản thuần tuý chứa các tín hiệu về tính toàn vẹn cùng với thông tin do nhà phát triển cung cấp.

Tải trọng có cấu trúc tổng quát như sau:

{
  requestDetails: { ... }
  appIntegrity: { ... }
  deviceIntegrity: { ... }
  accountDetails: { ... }
  environmentDetails: { ... }
}

Trước tiên, bạn phải kiểm tra để đảm bảo rằng các giá trị trong trường requestDetails khớp với các giá trị của yêu cầu ban đầu trước khi kiểm tra từng kết quả về tính toàn vẹn. Các phần sau đây sẽ mô tả chi tiết hơn về từng trường.

Trường thông tin chi tiết về yêu cầu

Trường requestDetails chứa thông tin về yêu cầu, bao gồm thông tin do nhà phát triển cung cấp trong requestHash đối với các yêu cầu thông thường và nonce đối với các yêu cầu kiểu cũ.

Đối với các yêu cầu API thông thường:

requestDetails: {
  // Application package name this attestation was requested for.
  // Note that this field might be spoofed in the middle of the request.
  requestPackageName: "com.package.name"
  // Request hash provided by the developer.
  requestHash: "aGVsbG8gd29scmQgdGhlcmU"
  // The timestamp in milliseconds when the integrity token
  // was requested.
  timestampMillis: "1675655009345"
}

Các giá trị này phải khớp với các giá trị trong yêu cầu ban đầu. Do đó, hãy xác minh phần requestDetails trong tải trọng JSON bằng cách đảm bảo requestPackageNamerequestHash khớp với nội dung đã gửi trong yêu cầu ban đầu như được minh hoạ trong đoạn mã sau:

Kotlin

val requestDetails = JSONObject(payload).getJSONObject("requestDetails")
val requestPackageName = requestDetails.getString("requestPackageName")
val requestHash = requestDetails.getString("requestHash")
val timestampMillis = requestDetails.getLong("timestampMillis")
val currentTimestampMillis = ...

// Ensure the token is from your app.
if (!requestPackageName.equals(expectedPackageName)
        // Ensure the token is for this specific request
    || !requestHash.equals(expectedRequestHash)
        // Ensure the freshness of the token.
    || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) {
        // The token is invalid! See below for further checks.
        ...
}

Java

RequestDetails requestDetails =
    decodeIntegrityTokenResponse
    .getTokenPayloadExternal()
    .getRequestDetails();
String requestPackageName = requestDetails.getRequestPackageName();
String requestHash = requestDetails.getRequestHash();
long timestampMillis = requestDetails.getTimestampMillis();
long currentTimestampMillis = ...;

// Ensure the token is from your app.
if (!requestPackageName.equals(expectedPackageName)
        // Ensure the token is for this specific request.
    || !requestHash.equals(expectedRequestHash)
        // Ensure the freshness of the token.
    || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) {
        // The token is invalid! See below for further checks.
        ...
}

Đối với các yêu cầu API kiểu cũ:

requestDetails: {
  // Application package name this attestation was requested for.
  // Note that this field might be spoofed in the middle of the
  // request.
  requestPackageName: "com.package.name"
  // base64-encoded URL-safe no-wrap nonce provided by the developer.
  nonce: "aGVsbG8gd29scmQgdGhlcmU"
  // The timestamp in milliseconds when the request was made
  // (computed on the server).
  timestampMillis: "1617893780"
}

Các giá trị này phải khớp với các giá trị trong yêu cầu ban đầu. Do đó, hãy xác minh phần requestDetails trong tải trọng JSON bằng cách đảm bảo requestPackageNamenonce khớp với nội dung đã gửi trong yêu cầu ban đầu như được minh hoạ trong đoạn mã sau:

Kotlin

val requestDetails = JSONObject(payload).getJSONObject("requestDetails")
val requestPackageName = requestDetails.getString("requestPackageName")
val nonce = requestDetails.getString("nonce")
val timestampMillis = requestDetails.getLong("timestampMillis")
val currentTimestampMillis = ...

// Ensure the token is from your app.
if (!requestPackageName.equals(expectedPackageName)
        // Ensure the token is for this specific request. See 'Generate a nonce'
        // section of the doc on how to store/compute the expected nonce.
    || !nonce.equals(expectedNonce)
        // Ensure the freshness of the token.
    || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) {
        // The token is invalid! See below for further checks.
        ...
}

Java

JSONObject requestDetails =
    new JSONObject(payload).getJSONObject("requestDetails");
String requestPackageName = requestDetails.getString("requestPackageName");
String nonce = requestDetails.getString("nonce");
long timestampMillis = requestDetails.getLong("timestampMillis");
long currentTimestampMillis = ...;

// Ensure the token is from your app.
if (!requestPackageName.equals(expectedPackageName)
        // Ensure the token is for this specific request. See 'Generate a nonce'
        // section of the doc on how to store/compute the expected nonce.
    || !nonce.equals(expectedNonce)
        // Ensure the freshness of the token.
    || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) {
        // The token is invalid! See below for further checks.
        ...
}

Trường tính toàn vẹn của ứng dụng

Trường appIntegrity chứa thông tin liên quan đến gói.

appIntegrity: {
  // PLAY_RECOGNIZED, UNRECOGNIZED_VERSION, or UNEVALUATED.
  appRecognitionVerdict: "PLAY_RECOGNIZED"
  // The package name of the app.
  // This field is populated iff appRecognitionVerdict != UNEVALUATED.
  packageName: "com.package.name"
  // The sha256 digest of app certificates (base64-encoded URL-safe).
  // This field is populated iff appRecognitionVerdict != UNEVALUATED.
  certificateSha256Digest: ["6a6a1474b5cbbb2b1aa57e0bc3"]
  // The version of the app.
  // This field is populated iff appRecognitionVerdict != UNEVALUATED.
  versionCode: "42"
}

appRecognitionVerdict có thể có các giá trị sau:

PLAY_RECOGNIZED
Ứng dụng và chứng chỉ khớp với các phiên bản do Google Play phân phối.
UNRECOGNIZED_VERSION
Chứng chỉ hoặc tên gói không khớp với bản ghi của Google Play.
UNEVALUATED
Tính toàn vẹn của ứng dụng chưa được đánh giá. Thiếu một yêu cầu cần thiết, chẳng hạn như thiết bị không đủ tin cậy.

Để đảm bảo rằng mã thông báo được tạo bởi một ứng dụng mà bạn tạo ra, hãy xác minh rằng tính toàn vẹn của ứng dụng đúng với dự kiến như trong đoạn mã sau:

Kotlin

val appIntegrity = JSONObject(payload).getJSONObject("appIntegrity")
val appRecognitionVerdict = appIntegrity.getString("appRecognitionVerdict")

if (appRecognitionVerdict == "PLAY_RECOGNIZED") {
    // Looks good!
}

Java

JSONObject appIntegrity =
    new JSONObject(payload).getJSONObject("appIntegrity");
String appRecognitionVerdict =
    appIntegrity.getString("appRecognitionVerdict");

if (appRecognitionVerdict.equals("PLAY_RECOGNIZED")) {
    // Looks good!
}

Bạn cũng có thể kiểm tra tên gói, phiên bản và chứng chỉ của ứng dụng theo cách thủ công.

Trường tính toàn vẹn của thiết bị

Trường deviceIntegrity có thể chứa một giá trị deviceRecognitionVerdict duy nhất. Giá trị này có một hoặc nhiều nhãn thể hiện mức độ hiệu quả của thiết bị trong việc thực thi tính toàn vẹn của ứng dụng. Nếu thiết bị không đáp ứng tiêu chí của bất kỳ nhãn nào, thì trường deviceIntegrity sẽ trống.

deviceIntegrity: {
  // "MEETS_DEVICE_INTEGRITY" is one of several possible values.
  deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"]
}

Theo mặc định, deviceRecognitionVerdict có thể chứa các thông tin sau:

MEETS_DEVICE_INTEGRITY
Ứng dụng đang chạy trên một thiết bị Android có Dịch vụ Google Play. Thiết bị vượt qua quy trình kiểm tra tính toàn vẹn của hệ thống và đáp ứng các yêu cầu về khả năng tương thích với Android.
Trống (giá trị trống)
Ứng dụng đang chạy trên một thiết bị có dấu hiệu bị tấn công (chẳng hạn như hook API) hoặc bị xâm phạm hệ thống (chẳng hạn như đã bị can thiệp vào hệ thống) hoặc ứng dụng không chạy trên một thiết bị thực (chẳng hạn như trình mô phỏng không vượt qua được quy trình kiểm tra tính toàn vẹn của Google Play).

Để đảm bảo rằng mã thông báo đến từ một thiết bị đáng tin cậy, hãy xác minh deviceRecognitionVerdict theo dự kiến như trong đoạn mã sau:

Kotlin

val deviceIntegrity =
    JSONObject(payload).getJSONObject("deviceIntegrity")
val deviceRecognitionVerdict =
    if (deviceIntegrity.has("deviceRecognitionVerdict")) {
        deviceIntegrity.getJSONArray("deviceRecognitionVerdict").toString()
    } else {
        ""
    }

if (deviceRecognitionVerdict.contains("MEETS_DEVICE_INTEGRITY")) {
    // Looks good!
}

Java

JSONObject deviceIntegrity =
    new JSONObject(payload).getJSONObject("deviceIntegrity");
String deviceRecognitionVerdict =
    deviceIntegrity.has("deviceRecognitionVerdict")
    ? deviceIntegrity.getJSONArray("deviceRecognitionVerdict").toString()
    : "";

if (deviceRecognitionVerdict.contains("MEETS_DEVICE_INTEGRITY")) {
    // Looks good!
}

Nếu bạn gặp sự cố liên quan đến tính toàn vẹn của thiết bị đang kiểm tra, hãy đảm bảo bạn đã cài đặt ROM gốc (ví dụ: bằng cách đặt lại thiết bị) và đã khoá trình tải khởi động. Bạn cũng có thể tạo phép kiểm thử API Tính toàn vẹn của Play trong Play Console.

Nhãn thiết bị có điều kiện

Nếu ứng dụng của bạn đang được phát hành trên Google Play Games dành cho máy tính, thì deviceRecognitionVerdict cũng có thể chứa nhãn sau:

MEETS_VIRTUAL_INTEGRITY
Ứng dụng đang chạy trên một trình mô phỏng Android có Dịch vụ Google Play. Trình mô phỏng này vượt qua quy trình kiểm tra tính toàn vẹn của hệ thống và đáp ứng các yêu cầu chính về khả năng tương thích với Android.

Thông tin không bắt buộc về thiết bị

Nếu bạn chọn nhận các nhãn bổ sung trong kết quả về tính toàn vẹn, thì deviceRecognitionVerdict có thể chứa các nhãn bổ sung sau đây:

MEETS_BASIC_INTEGRITY
Ứng dụng này đang chạy trên một thiết bị đã vượt qua các bài kiểm tra cơ bản về tính toàn vẹn của hệ thống và yêu cầu Chứng thực khoá trên nền tảng Android đối với thiết bị chạy Android 13 trở lên. Có thể thiết bị này không đáp ứng yêu cầu về khả năng tương thích với Android và không được phê duyệt để sử dụng dịch vụ Google Play. Ví dụ: có thể thiết bị này đang chạy một phiên bản Android không xác định, dùng trình tải khởi động đã được mở khoá, khởi động chưa được xác minh hoặc chưa được nhà sản xuất chứng nhận.
MEETS_STRONG_INTEGRITY
Ứng dụng này đang chạy trên một thiết bị Android có Dịch vụ Google Play, đồng thời có sự đảm bảo chắc chắn về tính toàn vẹn của hệ thống, chẳng hạn như bằng chứng dựa trên phần cứng về tính toàn vẹn khi khởi động và đối với thiết bị chạy Android 13 trở lên, ứng dụng này yêu cầu phải có bản cập nhật bảo mật trong năm qua. Thiết bị vượt qua quy trình kiểm tra tính toàn vẹn của hệ thống và đáp ứng các yêu cầu về khả năng tương thích với Android.

Một thiết bị sẽ trả về nhiều nhãn thiết bị trong kết quả về tính toàn vẹn của thiết bị nếu từng tiêu chí của nhãn được đáp ứng.

Hoạt động gần đây trên thiết bị

Bạn cũng có thể chọn sử dụng hoạt động gần đây trên thiết bị. Hoạt động này cho biết số lần ứng dụng của bạn đã yêu cầu một mã thông báo về tính toàn vẹn trên một thiết bị cụ thể trong 1 giờ qua. Bạn có thể sử dụng hoạt động gần đây trên thiết bị để bảo vệ ứng dụng khỏi các thiết bị không mong muốn, hoạt động quá mức. Đây có thể là dấu hiệu của một cuộc tấn công đang diễn ra. Bạn có thể quyết định mức độ tin cậy cho mỗi cấp hoạt động gần đây trên thiết bị, dựa trên số lần bạn dự kiến ứng dụng của mình được cài đặt trên một thiết bị thông thường để yêu cầu một mã thông báo về tính toàn vẹn mỗi giờ.

Nếu bạn chọn nhận recentDeviceActivity, trường deviceIntegrity sẽ có 2 giá trị:

deviceIntegrity: {
  deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"]
  recentDeviceActivity: {
    // "LEVEL_2" is one of several possible values.
    deviceActivityLevel: "LEVEL_2"
  }
}

Định nghĩa deviceActivityLevel khác nhau giữa các chế độ và có thể có một trong các giá trị sau:

Mức độ hoạt động gần đây trên thiết bị Số yêu cầu mã thông báo về tính toàn vẹn của API chuẩn trên thiết bị này trong 1 giờ qua trên mỗi ứng dụng Số yêu cầu mã thông báo về tính toàn vẹn của API kiểu cũ trên thiết bị này trong 1 giờ qua trên mỗi ứng dụng
LEVEL_1 (thấp nhất) 10 video trở xuống 5 hoặc ít hơn
LEVEL_2 Từ 11 đến 25 Từ 6 đến 10
LEVEL_3 Từ 26 đến 50 Từ 11 đến 15
LEVEL_4 (cao nhất) Hơn 50 Trên 15
UNEVALUATED Hoạt động gần đây trên thiết bị chưa được đánh giá. Điều này có thể xảy ra vì:
  • Thiết bị không đủ tin cậy.
  • Google Play không xác định được phiên bản ứng dụng của bạn được cài đặt trên thiết bị đó.
  • Các vấn đề kỹ thuật trên thiết bị.

Thuộc tính thiết bị

Bạn cũng có thể chọn sử dụng thuộc tính thiết bị. Thuộc tính này cho biết phiên bản SDK Android của hệ điều hành Android đang chạy trên thiết bị. Trong tương lai, thuộc tính này có thể được mở rộng bằng các thuộc tính thiết bị khác.

Giá trị phiên bản SDK là số phiên bản SDK Android được xác định trong Build.VERSION_CODES. Phiên bản SDK sẽ không được đánh giá nếu thiếu một yêu cầu cần thiết. Trong trường hợp này, trường sdkVersion không được đặt; do đó, trường deviceAttributes sẽ trống. Điều này có thể xảy ra vì:

  • Thiết bị không đủ tin cậy.
  • Google Play không xác định được phiên bản ứng dụng của bạn được cài đặt trên thiết bị đó.
  • Đã xảy ra vấn đề kỹ thuật trên thiết bị.

Nếu bạn chọn nhận deviceAttributes, trường deviceIntegrity sẽ có trường bổ sung sau:

deviceIntegrity: {
  deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"]
  deviceAttributes: {
    // 33 is one possible value, which represents Android 13 (Tiramisu).
    sdkVersion: 33
  }
}

Trong trường hợp phiên bản SDK không được đánh giá, trường deviceAttributes sẽ được đặt như sau:

deviceIntegrity: {
  deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"]
  deviceAttributes: {}  // sdkVersion field is not set.
}

Trường thông tin chi tiết tài khoản

Trường accountDetails chứa một giá trị appLicensingVerdict duy nhất, đại diện cho trạng thái cấp phép của ứng dụng trên Google Play cho tài khoản người dùng đã đăng nhập trên thiết bị. Nếu tài khoản người dùng có giấy phép Play cho ứng dụng, thì tức là họ đã tải ứng dụng đó xuống hoặc mua ứng dụng đó trên Google Play.

accountDetails: {
  // This field can be LICENSED, UNLICENSED, or UNEVALUATED.
  appLicensingVerdict: "LICENSED"
}

appLicensingVerdict có thể có một trong những giá trị sau đây:

LICENSED
Người dùng có quyền sử dụng ứng dụng. Nói cách khác, người dùng đã cài đặt hoặc cập nhật ứng dụng của bạn qua Google Play trên thiết bị của họ.
UNLICENSED
Người dùng không có quyền sử dụng ứng dụng. Chẳng hạn như khi người dùng cài đặt ứng dụng của bạn không qua cửa hàng ứng dụng hoặc có được ứng dụng thông qua một bên khác không phải là Google Play. Bạn có thể cho người dùng thấy hộp thoại GET_LICENSED để khắc phục vấn đề này.
UNEVALUATED

Thông tin cấp phép/quyền chưa được đánh giá vì thiếu một yêu cầu cần thiết.

Điều này có thể xảy ra vì một vài lý do như sau:

  • Thiết bị không đủ tin cậy.
  • Google Play không xác định được phiên bản ứng dụng của bạn đã cài đặt trên thiết bị.
  • Người dùng chưa đăng nhập vào Google Play.

Để kiểm tra xem người dùng có quyền sử dụng ứng dụng của bạn hay không, hãy xác minh rằng appLicensingVerdict là đúng với dự kiến như trong đoạn mã sau:

Kotlin

val accountDetails = JSONObject(payload).getJSONObject("accountDetails")
val appLicensingVerdict = accountDetails.getString("appLicensingVerdict")

if (appLicensingVerdict == "LICENSED") {
    // Looks good!
}

Java

JSONObject accountDetails =
    new JSONObject(payload).getJSONObject("accountDetails");
String appLicensingVerdict = accountDetails.getString("appLicensingVerdict");

if (appLicensingVerdict.equals("LICENSED")) {
    // Looks good!
}

Trường thông tin chi tiết về môi trường

Bạn cũng có thể chọn nhận các tín hiệu bổ sung về môi trường. Tính năng đánh giá rủi ro khi truy cập vào ứng dụng cho ứng dụng của bạn biết liệu có ứng dụng nào đang chạy có thể dùng để chụp màn hình, hiển thị lớp phủ hoặc điều khiển thiết bị hay không. Kết quả của Play Protect cho bạn biết liệu Google Play Protect có được bật trên thiết bị hay không và liệu Play Protect có tìm thấy phần mềm độc hại đã biết hay không.

Nếu bạn đã chọn sử dụng kết quả đánh giá Rủi ro truy cập ứng dụng hoặc kết quả của Play Protect trong Google Play Console, thì phản hồi của API sẽ bao gồm trường environmentDetails. Trường environmentDetails có thể chứa hai giá trị là appAccessRiskVerdictplayProtectVerdict.

Kết quả đánh giá rủi ro truy cập ứng dụng

Sau khi bật, trường environmentDetails trong tải trọng API Tính toàn vẹn của Play sẽ chứa kết quả đánh giá mới về rủi ro khi truy cập vào ứng dụng.

{
  requestDetails: { ... }
  appIntegrity: { ... }
  deviceIntegrity: { ... }
  accountDetails: { ... }
  environmentDetails: {
      appAccessRiskVerdict: {
          // This field contains one or more responses, for example the following.
          appsDetected: ["KNOWN_INSTALLED", "UNKNOWN_INSTALLED", "UNKNOWN_CAPTURING"]
      }
 }
}

Nếu đã đánh giá rủi ro khi truy cập vào ứng dụng, appAccessRiskVerdict sẽ chứa trường appsDetected với một hoặc nhiều phản hồi. Các phản hồi này thuộc một trong hai nhóm sau, tuỳ thuộc vào nguồn cài đặt của các ứng dụng đã phát hiện:

  • Các ứng dụng trên Play hoặc các ứng dụng hệ thống: Các ứng dụng do Google Play cài đặt hoặc do nhà sản xuất thiết bị tải trước lên phân vùng hệ thống của thiết bị (được xác định bằng FLAG_SYSTEM). Phản hồi cho các ứng dụng đó có tiền tố là KNOWN_.

  • Các ứng dụng khác: Các ứng dụng không phải do Google Play cài đặt. Không bao gồm các ứng dụng do nhà sản xuất thiết bị tải trước lên phân vùng hệ thống. Phản hồi cho các ứng dụng như vậy có tiền tố là UNKNOWN_.

Các phản hồi sau đây có thể được trả về:

KNOWN_INSTALLED, UNKNOWN_INSTALLED
Có những ứng dụng đã cài đặt khớp với nguồn cài đặt tương ứng.
KNOWN_CAPTURING, UNKNOWN_CAPTURING
Có những ứng dụng đang chạy đã bật quyền có thể dùng để xem màn hình trong khi ứng dụng đó đang chạy. Quy tắc này không bao gồm mọi dịch vụ hỗ trợ tiếp cận đã xác minh mà Google Play đã biết chạy trên thiết bị này.
KNOWN_CONTROLLING, UNKNOWN_CONTROLLING
Có những ứng dụng đang chạy đã bật quyền có thể dùng để điều khiển thiết bị và trực tiếp điều khiển đầu vào vào ứng dụng của bạn, cũng như để thu thập dữ liệu đầu vào và đầu ra của ứng dụng. Quy tắc này không bao gồm mọi dịch vụ hỗ trợ tiếp cận đã xác minh mà Google Play đang chạy trên thiết bị này.
KNOWN_OVERLAYS, UNKNOWN_OVERLAYS
Có những ứng dụng đang chạy đã bật quyền có thể dùng để hiển thị lớp phủ trên ứng dụng của bạn. Quy tắc này không bao gồm mọi dịch vụ hỗ trợ tiếp cận đã xác minh mà Google Play biết đang chạy trên thiết bị này.
Trống (giá trị trống)

Tính năng đánh giá rủi ro truy cập ứng dụng sẽ không được đánh giá nếu thiếu một yêu cầu cần thiết. Trong trường hợp này, trường appAccessRiskVerdict sẽ trống. Điều này có thể xảy ra vì một vài lý do, bao gồm:

  • Thiết bị không đủ tin cậy.
  • Kiểu dáng thiết bị không phải là điện thoại, máy tính bảng hoặc thiết bị có thể gập lại.
  • Thiết bị không chạy Android 6 (API cấp 23) trở lên.
  • Google Play không xác định được phiên bản ứng dụng của bạn trên thiết bị đó.
  • Phiên bản Cửa hàng Google Play trên thiết bị đã lỗi thời.
  • Chỉ dành cho trò chơi: Tài khoản người dùng không có giấy phép Play cho trò chơi.
  • Một yêu cầu chuẩn được sử dụng với tham số verdictOptOut.
  • Bạn đã sử dụng một yêu cầu thông thường với phiên bản thư viện API Tính toàn vẹn của Play chưa hỗ trợ tính năng đánh giá rủi ro khi truy cập vào ứng dụng cho các yêu cầu thông thường.

Tính năng đánh giá rủi ro truy cập ứng dụng sẽ tự động loại trừ các dịch vụ hỗ trợ tiếp cận đã xác minh mà Google Play đã đánh giá bằng quy trình nâng cao của mình (do bất kỳ cửa hàng ứng dụng nào cài đặt trên thiết bị). "Được loại trừ" có nghĩa là các dịch vụ hỗ trợ tiếp cận đã xác minh chạy trên thiết bị sẽ không trả về phản hồi CAPTURING, CONTROLLING hoặc OVERLAYS trong kết quả đánh giá rủi ro truy cập ứng dụng. Để yêu cầu Google Play đánh giá nâng cao về khả năng hỗ trợ tiếp cận cho ứng dụng hỗ trợ tiếp cận, hãy phát hành ứng dụng đó trên Google Play và đảm bảo rằng ứng dụng của bạn có cờ isAccessibilityTool được đặt thành true trong tệp kê khai của ứng dụng hoặc yêu cầu đánh giá.

Bảng sau đây cung cấp một số ví dụ về kết quả và ý nghĩa của các kết quả đó (bảng này không liệt kê mọi kết quả có thể có):

Ví dụ về phản hồi đối với kết quả đánh giá rủi ro truy cập ứng dụng Diễn giải
appsDetected:
["KNOWN_INSTALLED"]
Chỉ có những ứng dụng đã cài đặt do Google Play nhận dạng hoặc do nhà sản xuất thiết bị tải trước lên phân vùng hệ thống.
Không có ứng dụng nào đang chạy dẫn đến kết quả ghi lại, kiểm soát hoặc lớp phủ.
appsDetected:
["KNOWN_INSTALLED",
"UNKNOWN_INSTALLED",
"UNKNOWN_CAPTURING"]
Có những ứng dụng do Google Play cài đặt hoặc do nhà sản xuất thiết bị tải trước lên phân vùng hệ thống.
Có nhiều ứng dụng khác đang chạy và được cấp quyền có thể dùng để xem màn hình hoặc ghi lại các dữ liệu đầu vào và đầu ra khác.
appsDetected:
["KNOWN_INSTALLED",
"KNOWN_CAPTURING",
"UNKNOWN_INSTALLED",
"UNKNOWN_CONTROLLING"]
Có những ứng dụng trên Play hoặc ứng dụng hệ thống đang chạy đã bật các quyền có thể dùng để xem màn hình hoặc ghi lại các dữ liệu đầu vào và đầu ra khác.
Ngoài ra, còn có các ứng dụng khác đang chạy có quyền có thể dùng để điều khiển thiết bị và trực tiếp điều khiển dữ liệu đầu vào vào ứng dụng của bạn.
appAccessRiskVerdict: {} Tính năng đánh giá rủi ro truy cập ứng dụng không được đánh giá vì thiếu một yêu cầu cần thiết. Ví dụ: thiết bị không đủ tin cậy.

Tuỳ thuộc vào mức độ rủi ro, bạn có thể quyết định kết hợp kết quả nào được chấp nhận để tiếp tục và kết quả nào bạn muốn thực hiện hành động. Đoạn mã sau đây minh hoạ một ví dụ xác minh rằng không có ứng dụng nào đang chạy có thể ghi lại màn hình hoặc điều khiển ứng dụng của bạn:

Kotlin

val environmentDetails =
    JSONObject(payload).getJSONObject("environmentDetails")
val appAccessRiskVerdict =
    environmentDetails.getJSONObject("appAccessRiskVerdict")

if (appAccessRiskVerdict.has("appsDetected")) {
    val appsDetected = appAccessRiskVerdict.getJSONArray("appsDetected").toString()
    if (!appsDetected.contains("CAPTURING") && !appsDetected.contains("CONTROLLING")) {
        // Looks good!
    }
}

Java

JSONObject environmentDetails =
    new JSONObject(payload).getJSONObject("environmentDetails");
JSONObject appAccessRiskVerdict =
    environmentDetails.getJSONObject("appAccessRiskVerdict");

if (appAccessRiskVerdict.has("appsDetected")) {
    String appsDetected = appAccessRiskVerdict.getJSONArray("appsDetected").toString()
    if (!appsDetected.contains("CAPTURING") && !appsDetected.contains("CONTROLLING")) {
        // Looks good!
    }
}
Khắc phục kết quả đánh giá rủi ro truy cập ứng dụng

Tuỳ thuộc vào mức độ rủi ro, bạn có thể quyết định kết quả rủi ro khi truy cập vào ứng dụng mà bạn muốn thực hiện hành động trước khi cho phép người dùng hoàn tất một yêu cầu hoặc hành động. Bạn có thể hiển thị cho người dùng một số lời nhắc không bắt buộc của Google Play sau khi kiểm tra kết quả đánh giá rủi ro khi truy cập vào ứng dụng. Bạn có thể hiển thị quyền CLOSE_UNKNOWN_ACCESS_RISK để yêu cầu người dùng đóng các ứng dụng không xác định gây ra kết quả đánh giá rủi ro truy cập ứng dụng, hoặc bạn có thể hiển thị quyền CLOSE_ALL_ACCESS_RISK để yêu cầu người dùng đóng tất cả ứng dụng (đã biết và chưa biết) gây ra kết quả đánh giá rủi ro truy cập ứng dụng.

Kết quả xác minh của Play Protect

Sau khi bật, trường environmentDetails trong trọng tải API Tính toàn vẹn của Play sẽ chứa kết quả kiểm tra của Play Protect:

environmentDetails: {
  playProtectVerdict: "NO_ISSUES"
}

playProtectVerdict có thể có một trong những giá trị sau đây:

NO_ISSUES
Play Protect đã bật và không phát hiện thấy bất kỳ vấn đề nào về ứng dụng trên thiết bị.
NO_DATA
Play Protect đã bật nhưng chưa quét. Thiết bị hoặc ứng dụng Cửa hàng Play gần đây có thể đã được đặt lại.
POSSIBLE_RISK
Play Protect đã bị tắt.
MEDIUM_RISK
Play Protect đã bật và phát hiện thấy các ứng dụng có khả năng gây hại được cài đặt trên thiết bị này.
HIGH_RISK
Play Protect đã bật và phát hiện thấy các ứng dụng nguy hiểm được cài đặt trên thiết bị này.
UNEVALUATED

Kết quả kiểm tra Play Protect chưa được đánh giá.

Điều này có thể xảy ra vì một vài lý do như sau:

  • Thiết bị không đủ tin cậy.
  • Chỉ dành cho trò chơi: Tài khoản người dùng không có giấy phép Play cho trò chơi.

Hướng dẫn về cách sử dụng kết quả kiểm tra của Play Protect

Máy chủ phụ trợ của ứng dụng có thể quyết định cách hành động dựa theo kết quả và khả năng chấp nhận rủi ro của bạn. Sau đây là một số đề xuất và hành động mà người dùng có thể thực hiện:

NO_ISSUES
Play Protect đang bật và không phát hiện thấy vấn đề nên người dùng không cần thực hiện hành động nào.
POSSIBLE_RISKNO_DATA
Khi nhận được những kết quả này, hãy yêu cầu người dùng kiểm tra để đảm bảo rằng Play Protect đang bật và đã thực hiện quy trình quét. NO_DATA chỉ nên xuất hiện trong một số trường hợp hiếm gặp.
MEDIUM_RISKHIGH_RISK
Tuỳ thuộc vào khả năng chấp nhận rủi ro, bạn có thể yêu cầu người dùng chạy Play Protect và xử lý các cảnh báo của Play Protect. Nếu người dùng không thể thực hiện các yêu cầu này, bạn có thể chặn họ thao tác trên máy chủ.