Esito dell'integrità

In questa pagina viene descritto come interpretare e utilizzare l'integrità restituita verdetto. Indipendentemente dal fatto che si effettui una richiesta API standard o classica, l'integrità l'esito viene restituito nello stesso formato con contenuti simili. L'integrità l'esito comunica informazioni sulla validità di dispositivi, app e . Il server dell'app può utilizzare il payload risultante in un file decriptato, un esito verificato per stabilire come procedere al meglio con una determinata azione o richiesta nell'app.

Formato dell'esito relativo all'integrità restituito

Il payload è in formato JSON in testo normale e contiene indicatori di integrità fornite dallo sviluppatore.

La struttura generale del payload è la seguente:

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

Devi prima verificare che i valori nel campo requestDetails corrispondano a questi della richiesta originale prima di controllare ogni esito relativo all'integrità. Le seguenti ogni campo viene descritto in modo più dettagliato.

Campo dettagli richiesta

Il campo requestDetails contiene informazioni sulla richiesta, tra cui: le informazioni fornite dallo sviluppatore nel requestHash per le richieste standard e nonce per le richieste classiche.

Per le richieste API standard:

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

Questi valori devono corrispondere a quelli della richiesta originale. Pertanto, verifica requestDetails parte del payload JSON, assicurandoti che requestPackageName e requestHash corrispondono a quanto inviato nell'originale come mostrato nello snippet di codice riportato di seguito:

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

Per le richieste API classiche:

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

Questi valori devono corrispondere a quelli della richiesta originale. Pertanto, verifica requestDetails parte del payload JSON, assicurandoti che requestPackageName e nonce corrispondono a quanto inviato nella richiesta originale, come mostrato nel seguente snippet di codice:

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

Campo Integrità dell'applicazione

Il campo appIntegrity contiene informazioni relative al pacchetto.

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 può avere i seguenti valori:

PLAY_RECOGNIZED
L'app e il certificato corrispondono alle versioni distribuite da su Google Play.
UNRECOGNIZED_VERSION
Il nome del certificato o del pacchetto non corrisponde a Google Riproduci i record.
UNEVALUATED
L'integrità dell'applicazione non è stata valutata. Un requisito necessario perso, ad esempio perché il dispositivo non è abbastanza attendibile.

Per assicurarti che il token sia stato generato da un'app creata da te, verifica che l'integrità dell'applicazione sia quella prevista, come mostrato nel codice che segue snippet:

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

Puoi anche controllare il nome del pacchetto e la versione dell'app e i certificati dell'app manualmente.

Campo Integrità del dispositivo

Il campo deviceIntegrity può contenere un singolo valore, deviceRecognitionVerdict, che ha una o più etichette che rappresentano l'efficacia di una dispositivo può imporre l'integrità dell'app. Se un dispositivo non soddisfa i criteri di etichette, il campo deviceIntegrity è vuoto.

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

Per impostazione predefinita, deviceRecognitionVerdict può contenere quanto segue:

MEETS_DEVICE_INTEGRITY
L'app viene eseguita su un dispositivo Android con Google Play Services. Il dispositivo supera i controlli relativi all'integrità del sistema e soddisfa Requisiti di compatibilità di Android.
Vuoto (valore vuoto)
L'app è in esecuzione su un dispositivo che presenta segni di attacchi (come l'hook delle API) o compromissione del sistema (ad esempio il rooting) oppure l'app non è in esecuzione su un dispositivo fisico (ad esempio un emulatore che non superare i controlli relativi all'integrità di Google Play).

Per assicurarti che il token provenga da un dispositivo attendibile, verifica deviceRecognitionVerdict è come previsto, come mostrato nel seguente codice snippet:

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

Se hai problemi relativi all'integrità del dispositivo per riunioni, assicurati che la ROM di fabbrica sia installata (ad esempio ripristinando il dispositivo) e che il bootloader sia bloccato. Puoi anche creare test dell'API Play Integrity nella tua Play Console.

Etichette condizionali dei dispositivi

Se la tua app viene rilasciata per Google Play Giochi per PC, i deviceRecognitionVerdict può anche contenere la seguente etichetta:

MEETS_VIRTUAL_INTEGRITY
L'app è installata su un emulatore Android con Google Play Services. L'emulatore supera i controlli relativi all'integrità del sistema e soddisfa requisiti fondamentali di compatibilità con Android.

Informazioni facoltative del dispositivo

Se attivi la ricezione di ulteriori etichette nell'esito relativo all'integrità, deviceRecognitionVerdict può contenere le seguenti etichette aggiuntive:

MEETS_BASIC_INTEGRITY
L'app è in esecuzione su un dispositivo che supera i test di base e controlli di integrità del sistema. Il dispositivo potrebbe non soddisfare la compatibilità Android requisiti e potrebbe non essere approvata per eseguire Google Play Services. Per esempio, sul dispositivo potrebbe essere in esecuzione una versione di Android non riconosciuta, disponi di un bootloader sbloccato o potrebbe non essere stato certificato dal produttore.
MEETS_STRONG_INTEGRITY
L'app viene eseguita su un dispositivo Android con Google Play Services e ha una solida garanzia di integrità del sistema, ad esempio: una prova dell'integrità di avvio supportata dall'hardware. Il dispositivo supera la verifica del sistema verifica l'integrità e soddisfi i requisiti di compatibilità di Android.

Un singolo dispositivo restituirà più etichette del dispositivo nell'integrità del dispositivo l'esito se viene soddisfatto tutti i criteri dell'etichetta.

Attività del dispositivo recente

Puoi anche attivare le attività recenti del dispositivo, che ti indicano Molte volte la tua app ha richiesto un token di integrità su un dispositivo specifico. nell'ultima ora. Puoi usare l'attività recente del dispositivo per proteggere la tua app da dispositivi inaspettati e iperattivi che potrebbero indicare un attacco attivo. Puoi decidere il livello di attendibilità di ogni livello di attività recente del dispositivo in base a come molte volte ti aspetti che l'app installata su un dispositivo tipico richieda un il token di integrità ogni ora.

Se attivi la ricezione di recentDeviceActivity, il campo deviceIntegrity avrà due valori:

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

Le definizioni di deviceActivityLevel differiscono da una modalità all'altra e possono avere uno dei seguenti valori:

Livello di attività recente del dispositivo Richieste di token di integrità dell'API standard su questo dispositivo nell'ultima ora per app Richieste di token di integrità dell'API classiche su questo dispositivo nell'ultima ora per app
LEVEL_1 (valore più basso) 10 o meno 5 o meno
LEVEL_2 Tra 11 e 25 Tra 6 e 10
LEVEL_3 Tra 26 e 50 Tra 11 e 15
LEVEL_4 (valore più alto) Più di 50 Più di 15
UNEVALUATED L'attività recente del dispositivo non è stata valutata. Ciò può accadere perché:
  • Il dispositivo non è abbastanza attendibile.
  • La versione dell'app installata sul dispositivo non è nota a Google Gioca.
  • Problemi tecnici sul dispositivo.

Campo dettagli account

Il campo accountDetails contiene un singolo valore, appLicensingVerdict, che rappresenta lo stato di licenza dell'app Google Play per l'account utente di connesso sul dispositivo. Se l'account utente dispone della licenza Google Play per l'app, significa che è stato scaricato o acquistato su Google Play.

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

appLicensingVerdict può avere uno dei seguenti valori:

LICENSED
L'utente dispone di autorizzazione per l'app. In altre parole, l'utente ha installato o acquistato la tua app su Google Play.
UNLICENSED
L'utente non dispone di autorizzazione per l'app. Questo accade quando, ad Ad esempio, l'utente installa la tua app tramite sideload o non la acquisisce da Google Play. Per risolvere il problema, puoi mostrare agli utenti la finestra di dialogo GET_LICENSED.
UNEVALUATED

I dettagli relativi alle licenze non sono stati valutati perché era necessario requisito non soddisfatto.

Questo potrebbe accadere per diversi motivi, tra cui:

  • Il dispositivo non è abbastanza attendibile.
  • La versione dell'app installata sul dispositivo non è nota a Google Gioca.
  • L'utente non ha eseguito l'accesso a Google Play.

Per controllare che l'utente disponga di diritti per l'app in questione, verifica che le appLicensingVerdict è come previsto, come mostrato nel seguente snippet di codice:

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

Campo dettagli ambiente

Puoi anche attivare indicatori aggiuntivi sull'ambiente. Accesso alle app indica alla tua app se sono in esecuzione altre app che potrebbero essere utilizzate per acquisire lo schermo, visualizzare overlay o controllare il dispositivo. Play Protect indica se Google Play Protect è attivo sul dispositivo e se ha rilevato malware noto.

Se hai attivato l'esito del rischio di accesso alle app o l'esito Play Protect in Google Play Console, la risposta dell'API includerà campo environmentDetails. Il campo environmentDetails può contenere due valori, appAccessRiskVerdict e playProtectVerdict.

Esito del rischio di accesso all'app (beta)

Una volta attivato, il campo environmentDetails nell'API Play Integrity conterrà il nuovo esito del rischio di accesso all'app.

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

Se è stato valutato il rischio di accesso all'app, appAccessRiskVerdict contiene il campo appsDetected con una o più risposte. Queste risposte rientrano in uno dei seguenti due gruppi seguenti, a seconda dell'origine di installazione delle app rilevate:

  • App di sistema o di Google Play: app installate da Google Play o precaricate dal produttore del dispositivo sulla partizione di sistema del dispositivo (identificato con FLAG_SYSTEM). Le risposte per queste app sono precedute dal prefisso KNOWN_.

  • Altre app: app non installate da Google Play. Ciò esclude app precaricate sulla partizione di sistema dal produttore del dispositivo. Risposte per queste app sono preceduti dal prefisso UNKNOWN_.

di Gemini Advanced.

È possibile restituire le seguenti risposte:

KNOWN_INSTALLED, UNKNOWN_INSTALLED
Sono presenti app installate che corrispondono all'origine di installazione corrispondente.
KNOWN_CAPTURING, UNKNOWN_CAPTURING
Sono presenti app in esecuzione con autorizzazioni abilitate che potrebbero essere utilizzate per visualizzare la schermata mentre l'app è in esecuzione. Sono escluse le istanze verificate i servizi di accessibilità noti a Google Play in esecuzione sul dispositivo.
KNOWN_CONTROLLING, UNKNOWN_CONTROLLING
Sono presenti app in esecuzione con autorizzazioni abilitate che potrebbero essere utilizzate per controllare il dispositivo, controllare direttamente gli ingressi nell'app e potrebbe essere utilizzati per acquisire input e output della tua app. Sono escluse le istanze verificate i servizi di accessibilità noti a Google Play in esecuzione sul dispositivo.
KNOWN_OVERLAYS, UNKNOWN_OVERLAYS
Sono presenti app in esecuzione con autorizzazioni abilitate che potrebbero essere utilizzate per visualizzare overlay sulla tua app. Esclude qualsiasi accessibilità verificata servizi noti a Google Play in esecuzione sul dispositivo.
EMPTY (valore vuoto)

Il rischio di accesso all'app non viene valutato se non è stato soddisfatto un requisito necessario. Nel In questo caso, il campo appAccessRiskVerdict è vuoto. Questo può accadere per per diversi motivi, tra cui:

  • Il dispositivo non è abbastanza attendibile.
  • Il fattore di forma del dispositivo non è uno smartphone, un tablet o un dispositivo pieghevole.
  • Sul dispositivo non è installato Android 6 (livello API 23) o versioni successive.
  • La versione dell'app installata sul dispositivo non è nota a Google Play.
  • La versione del Google Play Store sul dispositivo è obsoleta.
  • Solo giochi: l'account utente non ha una licenza Google Play per il gioco.
  • È stata usata una richiesta standard con il parametro verdictOptOut.
  • È stata usata una richiesta standard con una versione della libreria API Play Integrity che non supporta ancora il rischio di accesso all'app per le richieste standard.

Il rischio di accesso all'app esclude automaticamente i servizi di accessibilità verificati che siano stati sottoposti a una revisione migliorata dell'accessibilità di Google Play (installata qualsiasi store sul dispositivo). "Escluso" significa che l'accessibilità verificata in esecuzione sul dispositivo non restituiranno un'acquisizione, un controllo overlay la risposta nell'esito del rischio di accesso all'app. Per richiedere una versione avanzata di Google Riproduci la revisione dell'accessibilità per la tua app di accessibilità, pubblicala su Google Riproduci assicurandoti che il flag isAccessibilityTool della tua app sia impostato su true in il file manifest dell'app o richiedi una revisione.

La tabella seguente fornisce alcuni esempi di esiti e il relativo significato (questo non elenca tutti i risultati possibili):

Esempio di risposta sull'esito del rischio di accesso all'app Interpretazione
appsDetected:
["KNOWN_INSTALLED"]
Sono presenti solo app installate che sono riconosciute da Google Play o precaricate nella partizione di sistema dal produttore del dispositivo.
Non sono presenti app in esecuzione che comporterebbero l'acquisizione, il controllo o gli esiti in overlay.
appsDetected:
["KNOWN_INSTALLED",
"UNKNOWN_INSTALLED",
"UNKNOWN_CAPTURING"]
Esistono app installate da Google Play o precaricate sulla partizione di sistema dal produttore del dispositivo.
Ci sono altre app in esecuzione e con autorizzazioni attive che potrebbero essere usate per visualizzare lo schermo o acquisire altri input e output.
appsDetected:
["KNOWN_INSTALLED",
"KNOWN_CAPTURING",
"UNKNOWN_INSTALLED",
"UNKNOWN_CONTROLLING"]
È in esecuzione la riproduzione o un sistema con autorizzazioni attivate che potrebbero essere usate per visualizzare la schermata o acquisire altri input e output.
Esistono anche altre app in esecuzione con autorizzazioni attivate che possono essere usate per controllare il dispositivo e controllare direttamente gli ingressi nella tua app.
appAccessRiskVerdict: {} Il rischio di accesso all'app non viene valutato perché non è stato soddisfatto un requisito necessario. Ad esempio, il dispositivo non era abbastanza attendibile.

A seconda del livello di rischio, puoi decidere quale combinazione di esiti accettabile per procedere e sugli esiti sui quali vuoi prendere provvedimenti. La il seguente snippet di codice illustra un esempio di verifica che non siano presenti App in esecuzione che potrebbero acquisire la schermata o controllare la tua app:

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!
    }
}
Risolvi gli esiti del rischio di accesso all'app

A seconda del tuo livello di rischio, puoi decidere quali esiti del rischio di accesso alle app su cui vuoi intervenire prima di permettere all'utente di completare una richiesta o un'azione. Esistono dei messaggi facoltativi di Google Play che puoi mostrare all'utente dopo controllare l'esito del rischio di accesso all'app. Puoi mostrare CLOSE_UNKNOWN_ACCESS_RISK per chiedere all'utente di chiudere le app sconosciute che causano l'esito del rischio di accesso all'app oppure puoi mostrare CLOSE_ALL_ACCESS_RISK per chiedere all'utente di chiudere tutte le app (note e sconosciute) causando l'esito del rischio di accesso all'app.

Esito Play Protect

Una volta attivato, il campo environmentDetails nell'API Play Integrity conterrà l'esito di Play Protect:

environmentDetails: {
  playProtectVerdict: "NO_ISSUES"
}

playProtectVerdict può avere uno dei seguenti valori:

NO_ISSUES
Play Protect è attivo e non ha rilevato alcun problema con l'app sul dispositivo.
NO_DATA
Play Protect è attivo, ma non è stata ancora eseguita alcuna scansione. Il dispositivo o l'app Play Store potrebbe essere stata reimpostata di recente.
POSSIBLE_RISK
Play Protect è disattivato.
MEDIUM_RISK
Play Protect è attivo e ha trovato app potenzialmente dannose installate sul dispositivo.
HIGH_RISK
Play Protect è attivo e ha trovato app pericolose installate sul .
UNEVALUATED

L'esito di Play Protect non è stato valutato.

Questo potrebbe accadere per diversi motivi, tra cui:

  • Il dispositivo non è abbastanza attendibile.
  • Solo giochi: l'account utente non ha una licenza Google Play per il gioco.

Indicazioni sull'utilizzo dell'esito di Play Protect

Il server di backend dell'app può decidere come agire in base all'esito in base la tua tolleranza al rischio. Ecco alcuni suggerimenti e potenziali azioni degli utenti:

NO_ISSUES
Play Protect è attivo e non ha rilevato problemi, quindi non è richiesta alcuna azione da parte dell'utente.
POSSIBLE_RISK e NO_DATA
Quando ricevi questi esiti, chiedi all'utente di verificare che Play Protect sia attivo e ha eseguito la scansione. NO_DATA deve apparire solo in rare circostanze.
MEDIUM_RISK e HIGH_RISK
A seconda della tua tolleranza al rischio, puoi chiedere all'utente di avviare Google Play Protect e prendi provvedimenti in merito agli avvisi di Play Protect. Se l'utente non riesce a completare per questi requisiti, potresti impedire loro di eseguire l'azione del server.