Wenn Sie nur Standard-API-Anfragen stellen möchten, die für die meisten Entwickler geeignet sind, können Sie mit dem Abschnitt Integritätsurteile fortfahren. Auf dieser Seite wird beschrieben, wie Sie klassische API-Anfragen für Integritätsprüfungen stellen, die ab Android 4.4 (API-Level 19) unterstützt werden.
Wissenswertes
Standard- und klassische Anfragen vergleichen
Je nach den Sicherheits- und Missbrauchsschutzanforderungen Ihrer App können Sie Standardanfragen, klassische Anfragen oder eine Kombination aus beidem senden. Standardanfragen eignen sich für alle Apps und Spiele. Mit ihnen lässt sich prüfen, ob eine Aktion oder ein Serveraufruf echt ist. Gleichzeitig wird ein gewisser Schutz vor Replay-Angriffen und Exfiltration an Google Play delegiert. Klassische Anfragen sind teurer und Sie sind dafür verantwortlich, sie korrekt zu implementieren, um sich vor Exfiltration und bestimmten Arten von Angriffen zu schützen. Klassische Anfragen sollten seltener als Standardanfragen gestellt werden, z. B. als gelegentliche einmalige Anfrage, um zu prüfen, ob eine sehr wertvolle oder sensible Aktion echt ist.
In der folgenden Tabelle sind die wichtigsten Unterschiede zwischen den beiden Arten von Anfragen aufgeführt:
Standard-API-Anfrage | Klassische API-Anfrage | |
---|---|---|
Voraussetzungen | ||
Mindestanforderung an die Android SDK-Version | Android 5.0 (API‑Level 21) oder höher | Android 4.4 (API‑Level 19) oder höher |
Google Play-Anforderungen | Google Play Store und Google Play-Dienste | Google Play Store und Google Play-Dienste |
Integrationsdetails | ||
API-Warm-up erforderlich | ✔️ (einige Sekunden) | ❌ |
Typische Anfragelatenz | Einige Hundert Millisekunden | Ein paar Sekunden |
Mögliche Häufigkeit von Anfragen | Häufig (On-Demand-Prüfung für jede Aktion oder Anfrage) | Selten (einmalige Prüfung für Aktionen mit dem höchsten Wert oder die vertraulichsten Anfragen) |
Zeitüberschreitungen | Die meisten Warm-ups dauern weniger als 10 Sekunden, erfordern aber einen Serveraufruf. Daher wird ein langes Zeitlimit empfohlen (z. B. 1 Minute). Anfragen zum Ergebnis werden clientseitig gestellt | Die meisten Anfragen dauern weniger als 10 Sekunden, erfordern aber einen Serveraufruf. Daher wird ein langes Zeitlimit empfohlen (z. B. 1 Minute). |
Integritätsergebnis-Token | ||
Enthält Details zu Geräten, Apps und Konten | ✔️ | ✔️ |
Token-Caching | Geschütztes On-Device-Caching durch Google Play | Nicht empfohlen |
Token über den Google Play-Server entschlüsseln und überprüfen | ✔️ | ✔️ |
Typische Latenz von Server-zu-Server-Anfragen für die Entschlüsselung | Zehntel von Millisekunden mit einer Verfügbarkeit von 99,9 % | Zehntel von Millisekunden mit einer Verfügbarkeit von 99,9 % |
Token lokal in einer sicheren Serverumgebung entschlüsseln und prüfen | ❌ | ✔️ |
Token clientseitig entschlüsseln und überprüfen | ❌ | ❌ |
Aktualität des Integritätsergebnisses | Einige automatische Caching- und Aktualisierungsvorgänge durch Google Play | Alle Entscheidungen werden bei jeder Anfrage neu berechnet |
Zeitbeschränkungen | ||
Anfragen pro App und Tag | Standardmäßig 10.000 (eine Erhöhung kann angefordert werden) | Standardmäßig 10.000 (eine Erhöhung kann angefordert werden) |
Anfragen pro App-Instanz und Minute | Aufwärmübungen: 5 pro Minute Integritätstokens: Kein öffentliches Limit* |
Integritätstokens: 5 pro Minute |
Schutz | ||
Schutz vor Manipulationen und ähnlichen Angriffen | Feld „requestHash “ verwenden |
nonce -Feld mit Inhaltsbindung basierend auf Anfragedaten verwenden |
Schutz vor Replay- und ähnlichen Angriffen | Automatische Risikominderung durch Google Play | Feld nonce mit serverseitiger Logik verwenden |
* Für alle Anfragen, auch für solche ohne öffentliche Limits, gelten bei hohen Werten nicht öffentliche defensive Limits.
Klassische Anfragen nur selten stellen
Das Generieren eines Integritätstokens erfordert Zeit, Daten und Akku. Jede App kann pro Tag nur eine bestimmte Anzahl klassischer Anfragen stellen. Daher sollten Sie klassische Anfragen nur dann stellen, um zu prüfen, ob die Aktionen mit dem höchsten Wert oder die vertraulichsten Aktionen echt sind, wenn Sie eine zusätzliche Garantie für eine Standardanfrage wünschen. Sie sollten keine klassischen Anfragen für Aktionen mit hoher Häufigkeit oder geringem Wert stellen. Stellen Sie nicht jedes Mal, wenn die App in den Vordergrund wechselt, oder alle paar Minuten im Hintergrund klassische Anfragen und vermeiden Sie es, gleichzeitig von einer großen Anzahl von Geräten aus Anfragen zu stellen. Wenn eine App zu viele klassische Anfragen stellt, kann sie gedrosselt werden, um Nutzer vor falschen Implementierungen zu schützen.
Zwischenspeichern von Ergebnissen vermeiden
Durch das Zwischenspeichern eines Ergebnisses steigt das Risiko von Angriffen wie Exfiltration und Replay, bei denen ein gutes Ergebnis aus einer nicht vertrauenswürdigen Umgebung wiederverwendet wird. Wenn Sie erwägen, eine klassische Anfrage zu stellen und sie dann für die spätere Verwendung zu speichern, empfiehlt es sich stattdessen, eine Standardanfrage bei Bedarf auszuführen. Bei Standardanfragen werden einige Daten auf dem Gerät zwischengespeichert. Google Play verwendet jedoch zusätzliche Schutzmechanismen, um das Risiko von Replay-Angriffen und Exfiltration zu minimieren.
Nonce-Feld zum Schutz klassischer Anfragen verwenden
Die Play Integrity API bietet das Feld nonce
, mit dem Sie Ihre App besser vor bestimmten Angriffen wie Replay- und Manipulationsangriffen schützen können. Die Play Integrity API gibt den Wert, den Sie in diesem Feld festlegen, in der signierten Integritätsantwort zurück. Folgen Sie der Anleitung zum Generieren von Nounces, um Ihre App vor Angriffen zu schützen.
Klassische Anfragen mit exponentiellem Backoff wiederholen
Umgebungsbedingungen wie eine instabile Internetverbindung oder ein überlastetes Gerät können dazu führen, dass die Prüfungen zur Geräteintegrität fehlschlagen. Das kann dazu führen, dass für ein ansonsten vertrauenswürdiges Gerät keine Labels generiert werden. Um diese Szenarien zu vermeiden, sollten Sie eine Wiederholungsoption mit exponentiellem Backoff einfügen.
Übersicht
Wenn der Nutzer in Ihrer App eine wertvolle Aktion ausführt, die Sie mit einer Integritätsprüfung schützen möchten, führen Sie die folgenden Schritte aus:
- Das serverseitige Backend Ihrer App generiert einen eindeutigen Wert und sendet ihn an die clientseitige Logik. In den verbleibenden Schritten wird diese Logik als „App“ bezeichnet.
- Ihre App erstellt den
nonce
aus dem eindeutigen Wert und dem Inhalt Ihrer wertvollen Aktion. Anschließend wird die Play Integrity API aufgerufen und dienonce
wird übergeben. - Ihre App erhält ein signiertes und verschlüsseltes Ergebnis von der Play Integrity API.
- Ihre App übergibt das signierte und verschlüsselte Ergebnis an das Backend Ihrer App.
- Das Backend Ihrer App sendet das Ergebnis an einen Google Play-Server. Der Google Play-Server entschlüsselt und überprüft das Ergebnis und gibt die Ergebnisse an das Backend Ihrer App zurück.
- Das Backend Ihrer App bestimmt anhand der Signale in der Token-Nutzlast, wie vorgegangen werden soll.
- Das Backend Ihrer App sendet die Entscheidungsergebnisse an Ihre App.
Nonce generieren
Wenn Sie eine Aktion in Ihrer App mit der Play Integrity API schützen, können Sie das Feld nonce
nutzen, um bestimmte Arten von Angriffen wie Man-in-the-Middle-Angriffe (MITM) und Replay-Angriffe zu verhindern. Die Play Integrity API gibt den Wert, den Sie in diesem Feld festgelegt haben, in der signierten Integritätsantwort zurück.
Der im Feld nonce
festgelegte Wert muss korrekt formatiert sein:
String
- URL-sicher
- Als Base64 codiert und nicht umgebrochen
- Mindestens 16 Zeichen
- Maximal 500 Zeichen.
Im Folgenden finden Sie einige gängige Möglichkeiten, das Feld nonce
in der Play Integrity API zu verwenden. Um den bestmöglichen Schutz vor nonce
zu erhalten, können Sie die folgenden Methoden kombinieren.
Anfrage-Hash zum Schutz vor Manipulationen einfügen
Sie können den Parameter nonce
in einer klassischen API-Anfrage ähnlich wie den Parameter requestHash
in einer Standard-API-Anfrage verwenden, um den Inhalt einer Anfrage vor Manipulationen zu schützen.
Wenn Sie ein Integritätsergebnis anfordern, gilt Folgendes:
- Berechnen Sie einen Hash aller kritischen Anfrageparameter (z.B. SHA256 einer stabilen Anfrage-Serialisierung) aus der Nutzeraktion oder Serveranfrage, die gerade stattfindet.
- Verwenden Sie
setNonce
, um das Feldnonce
auf den Wert des berechneten Digests festzulegen.
Wenn Sie ein Integritätsergebnis erhalten:
- Decodieren und prüfen Sie das Integritätstoken und rufen Sie den Digest aus dem Feld
nonce
ab. - Berechnen Sie einen Digest der Anfrage auf dieselbe Weise wie in der App (z.B. SHA256 einer stabilen Anfrage-Serialisierung).
- Vergleichen Sie die App- und Serverseiten-Zusammenfassungen. Wenn sie nicht übereinstimmen, ist die Anfrage nicht vertrauenswürdig.
Eindeutige Werte einfügen, um Replay-Angriffe zu verhindern
Damit böswillige Nutzer frühere Antworten der Play Integrity API nicht wiederverwenden können, können Sie das Feld nonce
verwenden, um jede Nachricht eindeutig zu identifizieren.
Wenn Sie ein Integritätsergebnis anfordern, gilt Folgendes:
- Einen global eindeutigen Wert auf eine Weise abrufen, die für böswillige Nutzer nicht vorhersehbar ist. Ein solcher Wert kann beispielsweise eine kryptografisch sichere Zufallszahl sein, die serverseitig generiert wird, oder eine bereits vorhandene ID wie eine Sitzungs- oder Transaktions-ID. Eine einfachere und weniger sichere Variante ist, eine Zufallszahl auf dem Gerät zu generieren. Wir empfehlen, Werte mit einer Länge von mindestens 128 Bit zu erstellen.
- Rufen Sie
setNonce()
auf, um das Feldnonce
auf den eindeutigen Wert aus Schritt 1 festzulegen.
Wenn Sie ein Integritätsergebnis erhalten:
- Decodieren und prüfen Sie das Integritätstoken und rufen Sie den eindeutigen Wert aus dem Feld
nonce
ab. - Wenn der Wert aus Schritt 1 auf dem Server generiert wurde, prüfen Sie, ob der empfangene eindeutige Wert einer der generierten Werte ist und zum ersten Mal verwendet wird. Ihr Server muss die generierten Werte für einen angemessenen Zeitraum aufzeichnen. Wenn der empfangene eindeutige Wert bereits verwendet wurde oder nicht im Datensatz enthalten ist, lehnen Sie die Anfrage ab.
- Wenn der eindeutige Wert auf dem Gerät generiert wurde, prüfen Sie, ob der empfangene Wert zum ersten Mal verwendet wird. Ihr Server muss bereits gesehene Werte für einen angemessenen Zeitraum aufzeichnen. Wenn der empfangene eindeutige Wert bereits verwendet wurde, lehnen Sie die Anfrage ab.
Beide Schutzmaßnahmen gegen Manipulationen und Replay-Angriffe kombinieren (empfohlen)
Mit dem Feld nonce
können Sie sich gleichzeitig vor Manipulationen und Replay-Angriffen schützen. Generieren Sie dazu den eindeutigen Wert wie oben beschrieben und fügen Sie ihn in Ihre Anfrage ein. Berechnen Sie dann den Anfrage-Hash und achten Sie darauf, dass der eindeutige Wert Teil des Hash ist. Eine Implementierung, die beide Ansätze kombiniert, sieht so aus:
Wenn Sie ein Integritätsergebnis anfordern, gilt Folgendes:
- Der Nutzer führt die Aktion mit hohem Umsatzpotenzial aus.
- Rufen Sie einen eindeutigen Wert für diese Aktion ab, wie im Abschnitt Eindeutige Werte zum Schutz vor Replay-Angriffen einfügen beschrieben.
- Bereiten Sie eine Nachricht vor, die Sie schützen möchten. Fügen Sie den eindeutigen Wert aus Schritt 2 in die Nachricht ein.
- Ihre App berechnet einen Digest der Nachricht, die sie schützen möchte, wie im Abschnitt Anfrage-Hash zum Schutz vor Manipulationen einfügen beschrieben. Da die Nachricht den eindeutigen Wert enthält, ist er Teil des Hashs.
- Verwenden Sie
setNonce()
, um das Feldnonce
auf den berechneten Digest aus dem vorherigen Schritt festzulegen.
Wenn Sie ein Integritätsergebnis erhalten:
- Eindeutigen Wert aus der Anfrage abrufen
- Decodieren und prüfen Sie das Integritätstoken und rufen Sie den Digest aus dem Feld
nonce
ab. - Wie im Abschnitt Anfrage-Hash zum Schutz vor Manipulationen einfügen beschrieben, berechnen Sie den Digest serverseitig neu und prüfen Sie, ob er mit dem Digest übereinstimmt, der aus dem Integritätstoken abgerufen wurde.
- Wie im Abschnitt Eindeutige Werte einfügen, um Replay-Angriffe zu verhindern beschrieben, müssen Sie die Gültigkeit des eindeutigen Werts prüfen.
Das folgende Sequenzdiagramm veranschaulicht diese Schritte mit einem serverseitigen nonce
:
Integritätsergebnis anfordern
Nachdem Sie eine nonce
generiert haben, können Sie ein Integritätsergebnis von Google Play anfordern. Führen Sie dazu folgende Schritte aus:
- Erstellen Sie ein
IntegrityManager
, wie in den folgenden Beispielen gezeigt. - Erstellen Sie ein
IntegrityTokenRequest
-Objekt und geben Sie dasnonce
-Objekt über die MethodesetNonce()
im zugehörigen Builder an. Apps, die ausschließlich außerhalb von Google Play vertrieben werden, und SDKs müssen ihre Google Cloud-Projektnummer auch über diesetCloudProjectNumber()
-Methode angeben. Apps bei Google Play sind mit einem Cloud-Projekt in der Play Console verknüpft. Die Cloud-Projektnummer muss daher nicht im Antrag angegeben werden. Rufen Sie
requestIntegrityToken()
mit dem Manager auf und geben Sie dieIntegrityTokenRequest
an.
Kotlin
// Receive the nonce from the secure server. val nonce: String = ... // Create an instance of a manager. val integrityManager = IntegrityManagerFactory.create(applicationContext) // Request the integrity token by providing a nonce. val integrityTokenResponse: Task<IntegrityTokenResponse> = integrityManager.requestIntegrityToken( IntegrityTokenRequest.builder() .setNonce(nonce) .build())
Java
import com.google.android.gms.tasks.Task; ... // Receive the nonce from the secure server. String nonce = ... // Create an instance of a manager. IntegrityManager integrityManager = IntegrityManagerFactory.create(getApplicationContext()); // Request the integrity token by providing a nonce. Task<IntegrityTokenResponse> integrityTokenResponse = integrityManager .requestIntegrityToken( IntegrityTokenRequest.builder().setNonce(nonce).build());
Unity
IEnumerator RequestIntegrityTokenCoroutine() { // Receive the nonce from the secure server. var nonce = ... // Create an instance of a manager. var integrityManager = new IntegrityManager(); // Request the integrity token by providing a nonce. var tokenRequest = new IntegrityTokenRequest(nonce); var requestIntegrityTokenOperation = integrityManager.RequestIntegrityToken(tokenRequest); // Wait for PlayAsyncOperation to complete. yield return requestIntegrityTokenOperation; // Check the resulting error code. if (requestIntegrityTokenOperation.Error != IntegrityErrorCode.NoError) { AppendStatusLog("IntegrityAsyncOperation failed with error: " + requestIntegrityTokenOperation.Error); yield break; } // Get the response. var tokenResponse = requestIntegrityTokenOperation.GetResult(); }
Unreal Engine
// .h void MyClass::OnRequestIntegrityTokenCompleted( EIntegrityErrorCode ErrorCode, UIntegrityTokenResponse* Response) { // Check the resulting error code. if (ErrorCode == EIntegrityErrorCode::Integrity_NO_ERROR) { // Get the token. FString Token = Response->Token; } } // .cpp void MyClass::RequestIntegrityToken() { // Receive the nonce from the secure server. FString Nonce = ... // Create the Integrity Token Request. FIntegrityTokenRequest Request = { Nonce }; // Create a delegate to bind the callback function. FIntegrityOperationCompletedDelegate Delegate; // Bind the completion handler (OnRequestIntegrityTokenCompleted) to the delegate. Delegate.BindDynamic(this, &MyClass::OnRequestIntegrityTokenCompleted); // Initiate the integrity token request, passing the delegate to handle the result. GetGameInstance() ->GetSubsystem<UIntegrityManager>() ->RequestIntegrityToken(Request, Delegate); }
Nativ
/// Create an IntegrityTokenRequest opaque object. const char* nonce = RequestNonceFromServer(); IntegrityTokenRequest* request; IntegrityTokenRequest_create(&request); IntegrityTokenRequest_setNonce(request, nonce); /// Prepare an IntegrityTokenResponse opaque type pointer and call /// IntegerityManager_requestIntegrityToken(). IntegrityTokenResponse* response; IntegrityErrorCode error_code = IntegrityManager_requestIntegrityToken(request, &response); /// ... /// Proceed to polling iff error_code == INTEGRITY_NO_ERROR if (error_code != INTEGRITY_NO_ERROR) { /// Remember to call the *_destroy() functions. return; } /// ... /// Use polling to wait for the async operation to complete. /// Note, the polling shouldn't block the thread where the IntegrityManager /// is running. IntegrityResponseStatus response_status; /// Check for error codes. IntegrityErrorCode error_code = IntegrityTokenResponse_getStatus(response, &response_status); if (error_code == INTEGRITY_NO_ERROR && response_status == INTEGRITY_RESPONSE_COMPLETED) { const char* integrity_token = IntegrityTokenResponse_getToken(response); SendTokenToServer(integrity_token); } /// ... /// Remember to free up resources. IntegrityTokenRequest_destroy(request); IntegrityTokenResponse_destroy(response); IntegrityManager_destroy();
Integritätsergebnis entschlüsseln und prüfen
Wenn Sie ein Integritätsergebnis anfordern, stellt die Play Integrity API ein signiertes Antworttoken bereit. Die nonce
, die Sie in Ihre Anfrage aufnehmen, wird Teil des Antwort-Tokens.
Token format
Das Token ist ein verschachteltes JSON Web Token (JWT), das JSON Web Encryption (JWE) von JSON Web Signature (JWS) ist. Die JWE- und JWS-Komponenten werden mit der kompakten Serialisierung dargestellt.
Die Verschlüsselungs- und Signaturalgorithmen werden in verschiedenen JWT-Implementierungen gut unterstützt:
Entschlüsseln und auf Google-Servern überprüfen (empfohlen)
Mit der Play Integrity API können Sie das Integritätsergebnis auf den Servern von Google entschlüsseln und überprüfen, was die Sicherheit Ihrer App erhöht. Führen Sie dazu die folgenden Schritte aus:
- Erstellen Sie ein Dienstkonto im Google Cloud-Projekt, das mit Ihrer App verknüpft ist.
Rufen Sie auf dem Server Ihrer App das Zugriffstoken mit den Anmeldedaten Ihres Dienstkontos über den Bereich
playintegrity
ab und stellen Sie die folgende Anfrage:playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken -d \ '{ "integrity_token": "INTEGRITY_TOKEN" }'
Lesen Sie die JSON-Antwort.
Lokal entschlüsseln und bestätigen
Wenn Sie Ihre Schlüssel zur Verschlüsselung von Antworten selbst verwalten und herunterladen, können Sie das zurückgegebene Token in Ihrer eigenen sicheren Serverumgebung entschlüsseln und überprüfen.
Sie können das zurückgegebene Token mit der Methode IntegrityTokenResponse#token()
abrufen.
Das folgende Beispiel zeigt, wie der AES-Schlüssel und der DER-codierte öffentliche EC-Schlüssel für die Signaturprüfung aus der Play Console in sprachspezifische (in diesem Fall Java) Schlüssel im Backend der App decodiert werden. Die Schlüssel sind mit Standard-Flags base64-codiert.
Kotlin
// base64OfEncodedDecryptionKey is provided through Play Console. var decryptionKeyBytes: ByteArray = Base64.decode(base64OfEncodedDecryptionKey, Base64.DEFAULT) // Deserialized encryption (symmetric) key. var decryptionKey: SecretKey = SecretKeySpec( decryptionKeyBytes, /* offset= */ 0, AES_KEY_SIZE_BYTES, AES_KEY_TYPE ) // base64OfEncodedVerificationKey is provided through Play Console. var encodedVerificationKey: ByteArray = Base64.decode(base64OfEncodedVerificationKey, Base64.DEFAULT) // Deserialized verification (public) key. var verificationKey: PublicKey = KeyFactory.getInstance(EC_KEY_TYPE) .generatePublic(X509EncodedKeySpec(encodedVerificationKey))
Java
// base64OfEncodedDecryptionKey is provided through Play Console. byte[] decryptionKeyBytes = Base64.decode(base64OfEncodedDecryptionKey, Base64.DEFAULT); // Deserialized encryption (symmetric) key. SecretKey decryptionKey = new SecretKeySpec( decryptionKeyBytes, /* offset= */ 0, AES_KEY_SIZE_BYTES, AES_KEY_TYPE); // base64OfEncodedVerificationKey is provided through Play Console. byte[] encodedVerificationKey = Base64.decode(base64OfEncodedVerificationKey, Base64.DEFAULT); // Deserialized verification (public) key. PublicKey verificationKey = KeyFactory.getInstance(EC_KEY_TYPE) .generatePublic(new X509EncodedKeySpec(encodedVerificationKey));
Verwenden Sie diese Schlüssel als Nächstes, um zuerst das Integritätstoken (JWE-Teil) zu entschlüsseln und dann den verschachtelten JWS-Teil zu überprüfen und zu extrahieren.
Kotlin
val jwe: JsonWebEncryption = JsonWebStructure.fromCompactSerialization(integrityToken) as JsonWebEncryption jwe.setKey(decryptionKey) // This also decrypts the JWE token. val compactJws: String = jwe.getPayload() val jws: JsonWebSignature = JsonWebStructure.fromCompactSerialization(compactJws) as JsonWebSignature jws.setKey(verificationKey) // This also verifies the signature. val payload: String = jws.getPayload()
Java
JsonWebEncryption jwe = (JsonWebEncryption)JsonWebStructure .fromCompactSerialization(integrityToken); jwe.setKey(decryptionKey); // This also decrypts the JWE token. String compactJws = jwe.getPayload(); JsonWebSignature jws = (JsonWebSignature) JsonWebStructure.fromCompactSerialization(compactJws); jws.setKey(verificationKey); // This also verifies the signature. String payload = jws.getPayload();
Die resultierende Nutzlast ist ein Nur-Text-Token, das Integritätsurteile enthält.
Probleme mit dem Ergebnis mithilfe einer Google Play-Aufforderung beheben (optional)
Nachdem Ihr Server ein Integritätsurteil erhalten hat, kann er entscheiden, wie er vorgehen soll. Wenn das Ergebnis auf ein Problem hinweist, z. B. dass die App keine Lizenz hat, manipuliert wurde oder das Gerät kompromittiert ist, können Sie Nutzern die Möglichkeit geben, das Problem selbst zu beheben.
Die Play Integrity API bietet die Möglichkeit, ein Google Play-Dialogfeld anzuzeigen, in dem der Nutzer aufgefordert wird, Maßnahmen zu ergreifen, z. B. die offizielle Version Ihrer App bei Google Play herunterzuladen.
Informationen dazu, wie Sie diese Dialogfelder basierend auf der Serverantwort in Ihrer App auslösen, finden Sie unter Dialogfelder zur Fehlerbehebung.