完全性判定の結果

このページでは、返された完全性判定の結果の解釈とその対応について説明します。標準 API リクエストとクラシック API リクエストのどちらを実行しても、完全性判定の結果は同じ形式で同様の内容が返されます。完全性判定の結果は、デバイス、アプリ、アカウントの有効性に関する情報を伝えます。アプリのサーバーは、復号と検証がなされた判定結果のペイロードを使用して、アプリ内の特定のアクションまたはリクエストを処理する最善の方法を決定できます。

返される完全性判定の結果の形式

返されるペイロードは書式なしテキスト JSON であり、デベロッパー提供の情報とともに完全性シグナルを含んでいます。

ペイロードの一般的な構造は次のとおりです。

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

個々の完全性判定の結果を確認する前に、requestDetails フィールドの値が元のリクエストの値と一致していることを確認する必要があります。以下のセクションでは、各フィールドについて詳しく説明します。

リクエストの詳細フィールド

requestDetails フィールドにはリクエストに関する情報が含まれます。この情報にはデベロッパー提供情報が含まれ、標準リクエストの場合は requestHash、クラシック リクエストの場合は nonce にあります。

標準 API リクエストの場合:

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"
}

これらの値は、元のリクエストの値と一致する必要があります。したがって、次のコード スニペットに示すように、requestPackageNamerequestHash が元のリクエストで送信されたものと一致することを確認して、JSON ペイロードの requestDetails の部分を検証します。

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.
        ...
}

クラシック API リクエストの場合:

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"
}

これらの値は、元のリクエストの値と一致する必要があります。したがって、次のコード スニペットに示すように、requestPackageNamenonce が元のリクエストで送信されたものと一致することを確認して、JSON ペイロードの requestDetails の部分を検証します。

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.
        ...
}

アプリの完全性フィールド

appIntegrity フィールドにはパッケージに関する情報が含まれます。

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 は次のいずれかの値を取ります。

PLAY_RECOGNIZED
アプリと証明書が、Google Play で配信されているバージョンと一致します。
UNRECOGNIZED_VERSION
証明書またはパッケージ名が Google Play の記録と一致しません。
UNEVALUATED
アプリの完全性は評価されませんでした。デバイスの信頼性が十分でないなど、要件が満たされていませんでした。

作成したアプリによってトークンが生成されたことを確認するには、次のコード スニペットに示すように、アプリの完全性が期待どおりであることを検証します。

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!
}

アプリのパッケージ名、アプリのバージョン、アプリの証明書を手動で確認することもできます。

デバイスの完全性フィールド

deviceIntegrity フィールドには deviceRecognitionVerdict という値のみが含まれます。この値には、デバイスがアプリの完全性をどの程度強化できるかを表すラベルが 1 つ以上含まれています。デバイスがラベルの基準を満たしていない場合、deviceIntegrity フィールドは空になります。

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

デフォルトでは、deviceRecognitionVerdict に含めることができる値は以下のとおりです。

MEETS_DEVICE_INTEGRITY
アプリは Google Play 開発者サービスを備えた Android デバイスで実行されています。このデバイスはシステム完全性チェックに合格し、Android の互換性要件を満たしています。
空(空の値)
アプリは、API フックなどの攻撃や root 権限取得などのシステム侵害の兆候があるデバイス、または Google Play の完全性チェックに合格していない仮想デバイス(エミュレータなど)で動作しています。

トークンが信頼できるデバイスから生成されたことを確認するには、次のコード スニペットに示すように、deviceRecognitionVerdict が期待どおりであることを検証します。

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!
}

テストデバイスがデバイスの完全性要件を満たさない問題が発生した場合は、工場出荷時の ROM がインストールされていることと、ブートローダーがロックされていることを確認してください(前者はデバイスをリセットするなどの方法で確認できます)。また、Google Play Console で Play Integrity API テストを作成することもできます。

条件付きのデバイスラベル

アプリを PC 版 Google Play Games にリリースする場合は、deviceRecognitionVerdict に次のラベルを付けることもできます。

MEETS_VIRTUAL_INTEGRITY
アプリは Google Play 開発者サービスを備えた Android エミュレータで実行されています。このエミュレータはシステム完全性チェックに合格し、Android の互換性に関する主要な要件を満たしています。

オプションのデバイス情報

完全性判定の結果で追加ラベルを受け取ることをオプトインすると、deviceRecognitionVerdict に以下のラベルを追加できます。

MEETS_BASIC_INTEGRITY
アプリは、基本的なシステム完全性チェックに合格したデバイスで動作しています。このデバイスは Android の互換性要件を満たしておらず、Google Play 開発者サービスの実行を承認されていない可能性があります。たとえば、認識されていないバージョンの Android を搭載している、ブートローダーがロック解除されている、メーカーによる認定を受けていない、などの場合があります。
MEETS_STRONG_INTEGRITY
アプリは、Google Play 開発者サービスを搭載した Android デバイスで動作しており、システム完全性の強力な保証(ハードウェア格納型のブート完全性保証など)が存在します。このデバイスはシステム完全性チェックに合格し、Android の互換性要件を満たしています。

ラベルのそれぞれの条件が満たされている場合、1 つのデバイスがデバイスの完全性判定の結果で複数のデバイスラベルを返します。

最近のデバイスのアクティビティ

最近のデバイスのアクティビティをオプトインすることもできます。これにより、過去 1 時間にアプリが特定のデバイスで完全性トークンをリクエストした回数を確認できます。最近のデバイスのアクティビティを使用することで、予期せぬ不審なアクティビティを過剰に行っている(アクティブな攻撃を示している可能性がある)デバイスからアプリを保護できます。一般的なデバイスにインストールされたアプリが 1 時間ごとに完全性トークンをリクエストする回数の予測に基づいて、最近のデバイスのアクティビティの信頼レベルを決定できます。

recentDeviceActivity を受け取ることをオプトインした場合、deviceIntegrity フィールドには以下の 2 つの値が含まれるようになります。

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

deviceActivityLevel の定義はモードによって異なり、次のいずれかの値に設定できます。

最近のデバイスのアクティビティ レベル 過去 1 時間にこのデバイスでアプリごとに行われた Standard API 完全性トークン リクエスト 過去 1 時間にこのデバイスでアプリごとに行われたクラシック API 完全性トークン リクエスト
LEVEL_1(最小) 10 本以下 5 以下
LEVEL_2 11 ~ 25 6 ~ 10 人
LEVEL_3 26 ~ 50 11 ~ 15
LEVEL_4(最高) 50 件以上 16 以上
UNEVALUATED 最近のデバイスのアクティビティは評価されませんでした。原因は次のとおりです。
  • デバイスの信頼性が十分でない。
  • デバイスにインストールされているアプリのバージョンが Google Play に認識されていない。
  • デバイスで技術的な問題が起きている。

デバイスの属性

デバイス属性を有効にすることもできます。デバイス属性は、デバイスで実行されている Android OS の Android SDK バージョンを示します。今後、他のデバイス属性が追加される可能性があります。

SDK バージョンの値は、Build.VERSION_CODES で定義された Android SDK バージョン番号です。必要な要件が満たされていない場合、SDK バージョンは評価されません。この場合、sdkVersion フィールドは設定されていないため、deviceAttributes フィールドは空になります。以下のような原因が考えられます。

  • デバイスの信頼性が十分でない。
  • デバイスにインストールされているアプリのバージョンが Google Play に認識されていない。
  • デバイスで技術的な問題が発生した。

deviceAttributes を受け取ることをオプトインすると、deviceIntegrity フィールドに次の追加フィールドが含まれるようになります。

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

SDK バージョンが評価されていない場合、deviceAttributes フィールドは次のように設定されます。

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

アカウントの詳細フィールド

accountDetails フィールドには appLicensingVerdict という値のみが含まれます。この値は、デバイスにログインしているユーザー アカウントに対するアプリの Google Play ライセンス ステータスを表します。ユーザー アカウントにアプリの Play ライセンスがある場合、そのアプリは Google Play からダウンロードまたは購入されたことを意味します。

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

appLicensingVerdict の値は次のいずれかになります。

LICENSED
ユーザーはアプリの利用資格を持っています。つまり、ユーザーはデバイスで Google Play からアプリをインストールまたは更新しました。
UNLICENSED
ユーザーはアプリの利用資格を持っていません。ユーザーがアプリをサイドローディングした場合や、アプリを Google Play から取得したのではない場合などが該当します。この問題の解決のために、ユーザーに対して [GET_LICENSED] ダイアログを表示できます。
UNEVALUATED

要件が満たされていないため、ライセンスの詳細は評価されませんでした。

次のような原因が考えられます。

  • デバイスの信頼性が十分でない。
  • デバイスにインストールされているアプリのバージョンが Google Play に認識されていない。
  • ユーザーが Google Play にログインしていない。

ユーザーにアプリの利用資格があるかどうかを確かめるには、次のコード スニペットに示すように、appLicensingVerdict が想定どおりであることを確認します。

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!
}

環境の詳細フィールド

環境に関する追加のシグナルをオプトインすることもできます。アプリアクセス リスクは、画面のキャプチャ、オーバーレイの表示、デバイスの制御に使用できる他のアプリが実行されているかどうかをアプリに通知します。Play プロテクトの判定結果は、デバイスで Google Play プロテクトが有効になっているか、既知のマルウェアが検出されたかどうかを示します。

Google Play Console でアプリアクセス リスクの判定結果または Play プロテクトの判定結果にオプトインしている場合は、API レスポンスに environmentDetails フィールドが含まれます。environmentDetails フィールドには、appAccessRiskVerdictplayProtectVerdict の 2 つの値を指定できます。

アプリアクセス リスクの判定結果

アカウント アクティビティを有効にすると、Play Integrity API ペイロードenvironmentDetails フィールドに、新しいアプリアクセス リスク判定結果が含まれます。

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

アプリアクセス リスクが評価された場合、appAccessRiskVerdict には 1 つ以上のレスポンスを含む appsDetected フィールドが含まれます。これらのレスポンスは、検出されたアプリのインストール元に応じて、次の 2 つのグループのいずれかに分類されます。

  • Play アプリまたはシステムアプリ: Google Play によってインストールされるアプリ、またはデバイスのシステム パーティション(FLAG_SYSTEM で識別される)にデバイスのメーカーによってプリロードされるアプリ。このようなアプリのレスポンスには KNOWN_ が先頭に付きます。

  • その他のアプリ: Google Play からインストールされていないアプリ。デバイスのメーカーによってシステム パーティションにプリロードされたアプリは除外されます。このようなアプリのレスポンスには UNKNOWN_ が付加されます。

返されるレスポンスは次のとおりです。

KNOWN_INSTALLEDUNKNOWN_INSTALLED
対応するインストール元に一致するアプリがインストールされています。
KNOWN_CAPTURINGUNKNOWN_CAPTURING
アプリの実行中に画面を表示するために使用できる権限が有効になっているアプリがあります。これには、デバイスで実行されている Google Play で認識されている検証済みのユーザー補助サービスは含まれません。
KNOWN_CONTROLLINGUNKNOWN_CONTROLLING
デバイスの制御やアプリへの入力の直接制御、アプリの入出力のキャプチャに使用できる権限が有効になっているアプリがあります。これには、デバイスで実行されている Google Play で認識されている検証済みのユーザー補助サービスは含まれません。
KNOWN_OVERLAYSUNKNOWN_OVERLAYS
アプリにオーバーレイを表示するために使用できる権限が有効になっているアプリがあります。これには、デバイスで実行されている Google Play で認識されている検証済みのユーザー補助サービスは含まれません。
空(空の値)

必要な要件が満たされていない場合、アプリアクセス リスクは評価されません。この場合、appAccessRiskVerdict フィールドは空です。次のような原因が考えられます。

  • デバイスの信頼性が十分でない。
  • デバイスのフォーム ファクタがスマートフォン、タブレット、折りたたみ式ではない。
  • デバイスで Android 6(API レベル 23)以降を実行していない。
  • デバイスにインストールされているアプリのバージョンが Google Play に認識されていない。
  • デバイス上の Google Play ストアのバージョンが古い。
  • ゲームのみ: ユーザー アカウントにゲームの Play ライセンスがない。
  • verdictOptOut パラメータを使用して標準リクエストが使用されました。
  • 標準リクエストのアプリアクセス リスクをまだサポートしていないバージョンの Play Integrity API ライブラリで標準リクエストが使用されています。

アプリアクセス リスクでは、Google Play のユーザー補助機能に関する高度な審査を経た検証済みのユーザー補助サービスは、(デバイス上の任意のアプリストアによってインストールされたもの)自動的に除外されます。「除外」とは、デバイスで実行されている検証済みユーザー補助サービスが、アプリアクセス リスク判定でキャプチャ、制御、オーバーレイのレスポンスを返さないことを意味します。ユーザー補助アプリの Google Play ユーザー補助機能に関する高度な審査をリクエストするには、アプリのマニフェストで isAccessibilityTool フラグを true に設定して Google Play に公開するか、審査をリクエストします。

次の表に、判定結果の例とその意味を示します(この表は可能な結果をすべて挙げたものではありません)。

アプリアクセス リスク判定結果のレスポンス例 解釈
appsDetected:
["KNOWN_INSTALLED"]
Google Play で認識されているインストール済みアプリ、またはデバイス メーカーによってシステム パーティションにプリロードされているアプリのみがあります。
CAPTURING、CONTROLLING、OVERLAY という判定結果となるアプリは実行されていません。
appsDetected:
["KNOWN_INSTALLED",
"UNKNOWN_INSTALLED",
"UNKNOWN_CAPTURING"]
Google Play によってインストールされたアプリ、またはデバイスのメーカーによってシステム パーティションにプリロードされたアプリがあります。
画面の表示や、他の入出力のキャプチャに使用できる権限が有効になっている実行中の他のアプリがあります。
appsDetected:
["KNOWN_INSTALLED",
"KNOWN_CAPTURING",
"UNKNOWN_INSTALLED",
"UNKNOWN_CONTROLLING"]
画面の表示や他の入出力のキャプチャに使用できる権限が有効になっている Play アプリまたはシステムアプリが実行されています。
また、デバイスの制御やアプリへの入力の直接制御に使用できる権限が有効になっている実行中の他のアプリがあります。
appAccessRiskVerdict: {} 要件が満たされていないため、アプリアクセス リスクは評価されませんでした(たとえば、デバイスの信頼性が十分ではなかった場合など)。

リスクレベルに応じて、続行できる判定結果の組み合わせと、対処する判定結果を決定できます。次のコード スニペットは、画面をキャプチャしたりアプリを操作したりする可能性のある実行中のアプリがないことを確認する例を示しています。

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!
    }
}
アプリアクセス リスクの判定結果を修正する

リスクレベルに応じて、ユーザーがリクエストまたはアクションを完了する前に、対処するアプリアクセス リスクの判定結果を決定できます。アプリアクセス リスクの判定結果を確認した後に、ユーザーに表示できる Google Play プロンプトがあります。CLOSE_UNKNOWN_ACCESS_RISK を表示して、アプリアクセス リスクの判定につながった不明なアプリを閉じるようにユーザーに求めることができます。また、CLOSE_ALL_ACCESS_RISK を表示して、アプリアクセス リスクの判定につながったすべてのアプリ(既知と不明)を閉じるようにユーザーに求めることもできます。

Play プロテクトの判定結果

有効にすると、Play Integrity API ペイロードenvironmentDetails フィールドに、Play プロテクトの判定結果が含まれます。

environmentDetails: {
  playProtectVerdict: "NO_ISSUES"
}

playProtectVerdict の値は次のいずれかになります。

NO_ISSUES
Play プロテクトはオンになっていますが、デバイスにおいてアプリの問題は検知されませんでした。
NO_DATA
Play プロテクトはオンになっていますが、まだスキャンが実行されていません。デバイスまたは Play ストア アプリが最近リセットされた可能性があります。
POSSIBLE_RISK
Play プロテクトがオフになっています。
MEDIUM_RISK
Play プロテクトがオンになっており、有害な可能性があるアプリがデバイスにインストールされていることが検知されました。
HIGH_RISK
Play プロテクトがオンになっており、危険なアプリがデバイスにインストールされていることが検知されました。
UNEVALUATED

Play プロテクトの判定結果は評価されませんでした。

次のような原因が考えられます。

  • デバイスの信頼性が十分でない。
  • ゲームのみ: ユーザー アカウントにゲームの Play ライセンスがない。

Play プロテクトの判定結果の使用に関するガイダンス

アプリのバックエンド サーバーは、リスク許容度に基づいて、判定結果に基づく処理方法を決定できます。推奨される使い方と、考えられるユーザーの操作には次のようなものがあります。

NO_ISSUES
Play プロテクトがオンになっていて、問題は検出されていないため、ユーザーの操作は必要ありません。
POSSIBLE_RISKNO_DATA
この判定結果を受け取ったら、Play プロテクトがオンになっていてスキャンが実行されているか確認するようユーザーに依頼します。NO_DATA はまれにしか表示されません。
MEDIUM_RISKHIGH_RISK
リスク許容度に応じて、Play プロテクトを起動し、Play プロテクトの警告に対応するようユーザーに依頼できます。ユーザーがこれらの要件を満たすことができない場合は、サーバー アクションからブロックできます。